paddlec 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'roctave'
4
+ require '../lib/paddlec'
5
+
6
+ def show_bar(f, t = 80.0)
7
+ p = (f.pos * t / f.size).round
8
+ STDOUT.write "\r[#{'='*p}>#{'-'*(t - p)}] "
9
+ STDOUT.flush
10
+ end
11
+
12
+
13
+ show_filters = false
14
+
15
+ fs = 2.048e6
16
+
17
+ # b = File.binread(File.expand_path '~/sdrrec/pouet.raw').unpack('C*').each_slice(2).collect{|a| Complex((a.first - 128) / 128.0, (a.last - 128) / 128.0)}.to_complex_buffer
18
+ # puts b.length
19
+ # File.binwrite('pouet_cf32le.raw', b.pack)
20
+ # exit
21
+
22
+
23
+ unless File.file? 'coefficients.f32le' then
24
+ STDOUT.write 'Generating filter coeficients... '; STDOUT.flush
25
+ now = Time.now
26
+
27
+ b_bbdecimator = Roctave.fir1(254, 95e3*2/fs)
28
+ Roctave.freqz(b_bbdecimator, :magnitude, nb_points: 2048, fs: fs) if show_filters
29
+
30
+ b_differentiator = Roctave.fir_differentiator(32)
31
+ Roctave.freqz(b_differentiator, :magnitude, nb_points: 2048, fs: fs/8) if show_filters
32
+
33
+ b_adecimator = Roctave.fir_low_pass(512, 15e3*2/256e3)
34
+ Roctave.freqz(b_adecimator, :magnitude, nb_points: 2048, fs: fs/8) if show_filters
35
+
36
+ tau = 50e-6
37
+ ts = 8*8/fs
38
+ b = [1 - Math.exp(-ts/tau)]
39
+ a = [1, -Math.exp(-ts/tau)]
40
+ h, w = Roctave.freqz(b, a, nb_points: 1024)
41
+ h.collect!{|v| v.abs}
42
+ w.collect!{|v| v/w.last}
43
+ n = 2048
44
+ b_deemphasis = Roctave.fir2(n, w, h, :odd_symmetry)
45
+ Roctave.freqz(b_deemphasis, :magnitude, nb_points: 2048, fs: fs/8/8) if show_filters
46
+
47
+ b_bppilote = Roctave.fir_band_pass(256, 2*19e3/(fs/8), 2*1e3/(fs/8))
48
+ Roctave.freqz(b_bppilote, :magnitude, nb_points: 2048, fs: fs/8) if show_filters
49
+
50
+ b_hilbert = Roctave.fir_hilbert(48, window: :blackman)
51
+ Roctave.freqz(b_hilbert, :magnitude, nb_points: 2048, fs: fs/8) if show_filters
52
+
53
+ b_bplmr = Roctave.fir_band_pass(256, 2*38e3/(fs/8), 2*30e3/(fs/8), window: :blackman)
54
+ Roctave.freqz(b_bplmr, :magnitude, nb_points: 2048, fs: fs/8) if show_filters
55
+
56
+ puts (Time.now - now).round(3)
57
+
58
+ File.open('coefficients.f32le', 'wb') do |ofile|
59
+ ofile.write b_bbdecimator.pack('f*')
60
+ ofile.write b_differentiator.pack('f*')
61
+ ofile.write b_adecimator.pack('f*')
62
+ ofile.write b_deemphasis.pack('f*')
63
+ ofile.write b_bppilote.pack('f*')
64
+ ofile.write b_hilbert.pack('f*')
65
+ ofile.write b_bplmr.pack('f*')
66
+ end
67
+ else
68
+ ifile = File.open('coefficients.f32le', 'rb')
69
+ b = ifile.read.unpack('f*')
70
+ ifile.close
71
+ b_bbdecimator = b.shift(255)
72
+ b_differentiator = b.shift(33)
73
+ b_adecimator = b.shift(513)
74
+ b_deemphasis = b.shift(2049)
75
+ b_bppilote = b.shift(257)
76
+ b_hilbert = b.shift(49)
77
+ b_bplmr = b.shift(257)
78
+ end
79
+
80
+
81
+
82
+ bbdecimator = PaddleC::FirDecimator.new b_bbdecimator, 8
83
+ differentiator = PaddleC::FirFilter.new b_differentiator
84
+ adecimator_lpr = PaddleC::FirDecimator.new b_adecimator, 8
85
+ adecimator_lmr = PaddleC::FirDecimator.new b_adecimator, 8
86
+ deemphasis_lpr = PaddleC::FirFilter.new b_deemphasis
87
+ deemphasis_lmr = PaddleC::FirFilter.new b_deemphasis
88
+ bppilote = PaddleC::FirFilter.new b_bppilote
89
+ bplmr = PaddleC::FirFilter.new b_bplmr
90
+ hilbert = PaddleC::FirTransformer.new b_hilbert
91
+ delay_p = PaddleC::Delay.new 152
92
+ delay_h = PaddleC::Delay.new 24
93
+
94
+ time_chunk = 100e-3
95
+ len = (32e3 * time_chunk).round
96
+
97
+ decoding = 0.0
98
+ waiting = 0.0
99
+ fname = '~/sdrrec/102.4MHz_2.048Msps_cu8.raw'
100
+ fname = '~/sdrrec/102.4MHz_2.048Msps_cu8_1.raw'
101
+ fname = '~/sdrrec/102.4MHz_2.048Msps_cu8_2.raw'
102
+ fname = '~/sdrrec/102.4MHz_2.048Msps_cu8_3.raw'
103
+ fname = '~/sdrrec/pouet.raw'
104
+ fname = '~/sdrrec/95.0MHz_2.048Msps_cu8.raw'
105
+ PaddleC::PulseAudio::Simple::Sink.open(stream_name: fname, sample_spec: 'float32 2ch 32000Hz') do |sink|
106
+ File.open(File.expand_path(fname), 'rb') do |f|
107
+ loop do
108
+ show_bar(f)
109
+
110
+ now = Time.now
111
+
112
+ if2MHz_complex = PaddleC::ComplexBuffer.unpack(f.read(8*8*len*2), :u8)
113
+
114
+ baseband256kHz_complex = bbdecimator.decimate(if2MHz_complex)
115
+
116
+ baseband_diff_complex, baseband_delayed_complex = differentiator.filter(baseband256kHz_complex, delayed: true)
117
+
118
+ demodulated = (baseband_diff_complex.imag*baseband_delayed_complex.real - baseband_diff_complex.real*baseband_delayed_complex.imag) / baseband_delayed_complex.abs2
119
+
120
+ pilote19 = bppilote.filter demodulated
121
+ pilote19c = hilbert.transform pilote19
122
+ pilote_phase = pilote19c.phase * 2
123
+ pilote38 = pilote_phase.sin
124
+
125
+ lmrh = bplmr.filter demodulated
126
+ lmrhd = delay_h.delay lmrh
127
+ lmrm = lmrhd * pilote38
128
+ lmremph = adecimator_lmr.decimate(lmrm)
129
+ lmr = deemphasis_lmr.filter(lmremph) * 0.25
130
+
131
+ lpremphdelayed = delay_p.delay demodulated
132
+ lpremph = adecimator_lpr.decimate(lpremphdelayed)
133
+ lpr = deemphasis_lpr.filter(lpremph) * 0.25
134
+
135
+ left = (lpr + lmr) / 2
136
+ right = (lpr - lmr) / 2
137
+
138
+ stereo = PaddleC::ComplexBuffer.new(left, right)
139
+
140
+ decoding += Time.now - now
141
+
142
+ now = Time.now
143
+
144
+ sink << stereo
145
+
146
+ waiting += Time.now - now
147
+
148
+ break if f.eof?
149
+ end
150
+ show_bar(f)
151
+ puts
152
+ end
153
+ end
154
+
155
+
156
+ puts "decoding took #{decoding.round(3)}s"
157
+ puts "waiting took #{waiting.round(3)}s"
158
+
159
+
160
+
161
+
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paddlec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Théotime Bollengier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: roctave
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.1
33
+ description: PaddleC is a Ruby C extension attempting to provide objects and methods
34
+ to rapidly set up real-time signal processing test benches in Ruby.
35
+ email: theotime.bollengier@gmail.com
36
+ executables: []
37
+ extensions:
38
+ - ext/paddlec/extconf.rb
39
+ extra_rdoc_files: []
40
+ files:
41
+ - LICENSE
42
+ - README.md
43
+ - ext/libpaddlec/arithmetic.c
44
+ - ext/libpaddlec/comparison.c
45
+ - ext/libpaddlec/complex.c
46
+ - ext/libpaddlec/delay.c
47
+ - ext/libpaddlec/fir_filter.c
48
+ - ext/libpaddlec/fir_filter_avx.c
49
+ - ext/libpaddlec/fir_filter_neon.c
50
+ - ext/libpaddlec/fir_filter_sse.c
51
+ - ext/libpaddlec/libpaddlec.c
52
+ - ext/libpaddlec/libpaddlec.h
53
+ - ext/libpaddlec/math.c
54
+ - ext/libpaddlec/no_fast_math.c
55
+ - ext/libpaddlec/rounding.c
56
+ - ext/paddlec/complex_buffer.c
57
+ - ext/paddlec/complex_buffer.h
58
+ - ext/paddlec/delay.c
59
+ - ext/paddlec/delay.h
60
+ - ext/paddlec/extconf.rb
61
+ - ext/paddlec/fir_filter.c
62
+ - ext/paddlec/fir_filter.h
63
+ - ext/paddlec/float_buffer.c
64
+ - ext/paddlec/float_buffer.h
65
+ - ext/paddlec/paddlec.c
66
+ - ext/paddlec/paddlec.h
67
+ - ext/paddlec/pulseaudio.c
68
+ - ext/paddlec/pulseaudio.h
69
+ - lib/paddlec.rb
70
+ - lib/paddlec/version.rb
71
+ - paddlec.gemspec
72
+ - samples/fmdemod.rb
73
+ - samples/fmdemod_chunk.rb
74
+ - samples/fmdemod_chunk_buffer.rb
75
+ - samples/stereo_chunk.rb
76
+ homepage: https://gitlab.com/theotime_bollengier/paddlec
77
+ licenses:
78
+ - GPL-3.0+
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubygems_version: 3.0.6
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: A Ruby C extension for real-time signal processing.
99
+ test_files: []