wavspa 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +196 -0
- data/Rakefile +2 -0
- data/bin/wavfft +167 -0
- data/bin/wavlet +160 -0
- data/example/Call_To_Quarters-fft.png +0 -0
- data/example/Call_To_Quarters-wavelet.png +0 -0
- data/ext/wavspa/fb/extconf.rb +3 -0
- data/ext/wavspa/fb/rb_fb.c +690 -0
- data/ext/wavspa/fft/extconf.rb +6 -0
- data/ext/wavspa/fft/fft.c +918 -0
- data/ext/wavspa/fft/fft.h +62 -0
- data/ext/wavspa/fft/fftsg.c +3314 -0
- data/ext/wavspa/fft/rb_fft.c +458 -0
- data/ext/wavspa/wavelet/extconf.rb +37 -0
- data/ext/wavspa/wavelet/rb_wavelet.c +706 -0
- data/ext/wavspa/wavelet/walet.c +803 -0
- data/ext/wavspa/wavelet/walet.h +59 -0
- data/lib/wav.rb +87 -0
- data/lib/wavspa/common.rb +74 -0
- data/lib/wavspa/version.rb +3 -0
- data/lib/wavspa/wavfft/main.rb +130 -0
- data/lib/wavspa/wavfft/preset.rb +54 -0
- data/lib/wavspa/wavlet/main.rb +139 -0
- data/lib/wavspa/wavlet/preset.rb +38 -0
- data/wavspa.gemspec +47 -0
- metadata +119 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
/*
|
2
|
+
* Wavelet transform library
|
3
|
+
*
|
4
|
+
* Copyright (C) 2016 Hiroshi Kuwagata <kgt9221@gmail.com>
|
5
|
+
*/
|
6
|
+
|
7
|
+
/*
|
8
|
+
* $Id: walet.h 91 2016-07-04 03:05:03Z kgt $
|
9
|
+
*/
|
10
|
+
|
11
|
+
#ifndef __WALET_H__
|
12
|
+
#define __WALET_H__
|
13
|
+
|
14
|
+
#include <stdio.h>
|
15
|
+
#include <stdlib.h>
|
16
|
+
#include <stdint.h>
|
17
|
+
|
18
|
+
#define WALET_LINEARSCALE_MODE 1
|
19
|
+
#define WALET_LOGSCALE_MODE 2
|
20
|
+
|
21
|
+
typedef struct __walet__ {
|
22
|
+
int flags;
|
23
|
+
|
24
|
+
double fq_s; // as "sampleing frequency"
|
25
|
+
double fq_l; // as "low side frequency"
|
26
|
+
double fq_h; // as "high side fequency"
|
27
|
+
|
28
|
+
double sigma;
|
29
|
+
double wk0;
|
30
|
+
double wk1;
|
31
|
+
double wk2;
|
32
|
+
int* ws; // as window size list
|
33
|
+
double** exp;
|
34
|
+
|
35
|
+
int width;
|
36
|
+
int mode;
|
37
|
+
double step;
|
38
|
+
|
39
|
+
double* smpl; // as "sample data"
|
40
|
+
int n; // as "number of sample size"
|
41
|
+
|
42
|
+
double* wt;
|
43
|
+
} walet_t;
|
44
|
+
|
45
|
+
int walet_new(walet_t** ptr);
|
46
|
+
int walet_destroy(walet_t* ptr);
|
47
|
+
|
48
|
+
int walet_set_sigma(walet_t* ptr, double sigma);
|
49
|
+
int walet_set_frequency(walet_t* ptr, double freq);
|
50
|
+
int walet_set_range(walet_t* ptr, double low, double high);
|
51
|
+
int walet_set_scale_mode(walet_t* ptr, int mode);
|
52
|
+
int walet_set_output_width(walet_t* ptr, int width);
|
53
|
+
|
54
|
+
int walet_put_in(walet_t* ptr, char* fmt, void* data, size_t size);
|
55
|
+
int walet_transform(walet_t* ptr, int pos);
|
56
|
+
int walet_calc_power(walet_t* ptr, double* dst);
|
57
|
+
int walet_calc_amplitude(walet_t* ptr, double* dst);
|
58
|
+
|
59
|
+
#endif /* !defined(__WALET_H__) */
|
data/lib/wav.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#coding utf-8
|
3
|
+
|
4
|
+
#
|
5
|
+
# WAV file parser
|
6
|
+
#
|
7
|
+
# Copyright (C) 2014 Hiroshi Kuwagata <kgt9221@gmail.com>
|
8
|
+
#
|
9
|
+
|
10
|
+
class WavFile
|
11
|
+
class << self
|
12
|
+
alias :open :new
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(file)
|
16
|
+
@io = File.open(file, "rb")
|
17
|
+
|
18
|
+
tmp = @io.read(12).unpack('a4Va4')
|
19
|
+
|
20
|
+
@magic = tmp[0]
|
21
|
+
@data_size = tmp[1]
|
22
|
+
@type = tmp[2]
|
23
|
+
|
24
|
+
if not (@magic == "RIFF" and @type == "WAVE")
|
25
|
+
raise('Illeagal magic number.')
|
26
|
+
end
|
27
|
+
|
28
|
+
if @data_size != (File.size(file) - 8)
|
29
|
+
raise('Data size is not match.')
|
30
|
+
end
|
31
|
+
|
32
|
+
tmp = @io.read(8).unpack('a4V')
|
33
|
+
|
34
|
+
@id = tmp[0]
|
35
|
+
|
36
|
+
if @id != 'fmt '
|
37
|
+
raise('ID "%s" is not supported.' % @id)
|
38
|
+
end
|
39
|
+
|
40
|
+
tmp = @io.read(tmp[1]).unpack('vvVVvv')
|
41
|
+
|
42
|
+
@format_id = tmp[0]
|
43
|
+
@channel_num = tmp[1]
|
44
|
+
@sample_rate = tmp[2]
|
45
|
+
@bytes_per_sec = tmp[3]
|
46
|
+
@block_size = tmp[4]
|
47
|
+
@sample_size = tmp[5]
|
48
|
+
|
49
|
+
loop {
|
50
|
+
tmp = @io.read(8).unpack('a4V')
|
51
|
+
break if tmp[0] == "data"
|
52
|
+
|
53
|
+
@io.seek(tmp[1], IO::SEEK_CUR)
|
54
|
+
}
|
55
|
+
|
56
|
+
@data_offset = @io.pos
|
57
|
+
@data_size = tmp[1]
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :data_size, :channel_num, :sample_rate, :sample_size,
|
61
|
+
:bytes_per_sec, :block_size
|
62
|
+
|
63
|
+
def read(n = nil)
|
64
|
+
if not n.nil?
|
65
|
+
@io.read(@block_size * n)
|
66
|
+
else
|
67
|
+
@io.read
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def seek(pos)
|
72
|
+
@io.seek(@block_size * pos, IO::SEEK_SET)
|
73
|
+
end
|
74
|
+
|
75
|
+
def eof?
|
76
|
+
@io.eof?
|
77
|
+
end
|
78
|
+
|
79
|
+
def close
|
80
|
+
@io.close
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
if $0 == __FILE__
|
85
|
+
require 'pp'
|
86
|
+
pp WavFile.open(ARGV[0])
|
87
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "wavspa/version"
|
2
|
+
|
3
|
+
module WavSpectrumAnalyzer
|
4
|
+
module Common
|
5
|
+
def log_scaler(r)
|
6
|
+
return 1.0 - ((Math.log(r / @lo_freq) / @log_base) / @output_width)
|
7
|
+
end
|
8
|
+
|
9
|
+
def linear_scaler(r)
|
10
|
+
return 1.0 - ((r - @lo_freq) / @freq_width)
|
11
|
+
end
|
12
|
+
|
13
|
+
def fpos(r)
|
14
|
+
scale = (@logscale)? log_scaler(r): linear_scaler(r)
|
15
|
+
return (scale * @output_width).round
|
16
|
+
end
|
17
|
+
|
18
|
+
def draw_freq_line(fb)
|
19
|
+
#
|
20
|
+
# 低周波方向
|
21
|
+
#
|
22
|
+
frq = @basis_freq / 2
|
23
|
+
loop {
|
24
|
+
pos = fpos(frq)
|
25
|
+
break if pos > @output_width
|
26
|
+
|
27
|
+
fb.hline(pos, "#{frq.to_i}Hz")
|
28
|
+
frq /= 2
|
29
|
+
}
|
30
|
+
|
31
|
+
#
|
32
|
+
# 高周波方向
|
33
|
+
#
|
34
|
+
frq = @basis_freq;
|
35
|
+
loop {
|
36
|
+
pos = fpos(frq)
|
37
|
+
break if pos <= 0
|
38
|
+
|
39
|
+
fb.hline(pos, "#{frq.to_i}Hz")
|
40
|
+
frq *= 2
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def time_str(tm)
|
45
|
+
m = tm / 60
|
46
|
+
s = tm % 60
|
47
|
+
|
48
|
+
if m.zero?
|
49
|
+
ret = %q{%d"} % s
|
50
|
+
else
|
51
|
+
ret = %q{%d'%02d"} % [m, s]
|
52
|
+
end
|
53
|
+
|
54
|
+
return ret
|
55
|
+
end
|
56
|
+
|
57
|
+
def draw_time_line(fb, wav, usize)
|
58
|
+
tc = 0
|
59
|
+
tm = 0
|
60
|
+
n = (wav.data_size / (wav.sample_size / 8)) / usize
|
61
|
+
|
62
|
+
fb.vline(0, time_str(tm))
|
63
|
+
|
64
|
+
n.times { |col|
|
65
|
+
tc += usize;
|
66
|
+
if tc >= wav.sample_rate
|
67
|
+
tm += 1
|
68
|
+
tc %= wav.sample_rate
|
69
|
+
fb.vline(col, time_str(tm)) if (tm % 10).zero?
|
70
|
+
end
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
#
|
5
|
+
# Spectrum analyzer for WAV file
|
6
|
+
#
|
7
|
+
# Copyright (C) 2019 Hiroshi Kuwagata <kgt9221@gmail.com>
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'wav'
|
11
|
+
require 'png'
|
12
|
+
|
13
|
+
require 'wavspa/fft'
|
14
|
+
require 'wavspa/fb'
|
15
|
+
|
16
|
+
module WavSpectrumAnalyzer
|
17
|
+
module FFTApp
|
18
|
+
extend WavSpectrumAnalyzer::Common
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def load_param(param)
|
22
|
+
@unit_time = param[:unit_time]
|
23
|
+
@fft_size = param[:fft_size]
|
24
|
+
@output_width = param[:output_width]
|
25
|
+
@logscale = (param[:scale_mode] == :LOGSCALE)
|
26
|
+
@win_func = param[:window_function]
|
27
|
+
@scale_mode = param[:scale_mode]
|
28
|
+
@col_step = param[:col_step]
|
29
|
+
|
30
|
+
@freq_range = param[:range]
|
31
|
+
@lo_freq = @freq_range[0]
|
32
|
+
@hi_freq = @freq_range[1]
|
33
|
+
@freq_width = (@hi_freq - @lo_freq)
|
34
|
+
|
35
|
+
@log_step = (@hi_freq / @lo_freq) ** (1.0 / @output_width)
|
36
|
+
@log_base = Math.log(@log_step)
|
37
|
+
@basis_freq = 440.0
|
38
|
+
end
|
39
|
+
private :load_param
|
40
|
+
|
41
|
+
def main(input, param, output)
|
42
|
+
load_param(param)
|
43
|
+
|
44
|
+
wav = WavFile.open(input)
|
45
|
+
fft = FFT.new("s%dle" % wav.sample_size, @fft_size)
|
46
|
+
|
47
|
+
fft.window = @win_func
|
48
|
+
fft.width = @output_width
|
49
|
+
fft.scale_mode = @scale_mode
|
50
|
+
fft.frequency = @freq_range.clone.unshift(wav.sample_rate)
|
51
|
+
|
52
|
+
line = []
|
53
|
+
rows = 0
|
54
|
+
usize = (wav.sample_rate / 100) * @unit_time
|
55
|
+
nblk = (wav.data_size / (wav.sample_size / 8)) / usize
|
56
|
+
|
57
|
+
fb = FrameBuffer.new(nblk,
|
58
|
+
@output_width,
|
59
|
+
:column_step => @col_step,
|
60
|
+
:margin_x => ($draw_freq_line)? 50:0,
|
61
|
+
:margin_y => ($draw_time_line)? 30:0)
|
62
|
+
|
63
|
+
if $verbose
|
64
|
+
STDERR.print <<~EOT
|
65
|
+
- input data
|
66
|
+
#{input}
|
67
|
+
data size: #{wav.data_size}
|
68
|
+
channel num: #{wav.channel_num}
|
69
|
+
sample rate: #{wav.sample_rate} Hz
|
70
|
+
sample size: #{wav.sample_size} bits
|
71
|
+
data rate: #{wav.bytes_per_sec} bytes/sec
|
72
|
+
|
73
|
+
- FFT parameter
|
74
|
+
FFT size: #{@fft_size} samples
|
75
|
+
unit time: #{@unit_time} cs
|
76
|
+
window func: #{@win_func}
|
77
|
+
|
78
|
+
- OUTPUT
|
79
|
+
width: #{fb.width}px
|
80
|
+
height: #{fb.height}px
|
81
|
+
freq range: #{@lo_freq} - #{@hi_freq}Hz
|
82
|
+
scale mode: #{@scale_mode}
|
83
|
+
|
84
|
+
EOT
|
85
|
+
end
|
86
|
+
|
87
|
+
if wav.channel_num >= 2
|
88
|
+
STDERR.print("error: multi chanel data is not supported " \
|
89
|
+
"(support only monoral data).\n")
|
90
|
+
exit(1)
|
91
|
+
end
|
92
|
+
|
93
|
+
until rows >= nblk
|
94
|
+
STDERR.printf("\rtransform #{rows + 1}/#{nblk}", rows) if $verbose
|
95
|
+
|
96
|
+
fft << wav.read(usize)
|
97
|
+
|
98
|
+
fft.spectrum.unpack("d*").each {|x|
|
99
|
+
begin
|
100
|
+
x = (x * 3.5).round
|
101
|
+
x = 0 if x < 0
|
102
|
+
x = 255 if x > 255
|
103
|
+
rescue
|
104
|
+
x = 0
|
105
|
+
end
|
106
|
+
|
107
|
+
line.unshift(x / 3, x, x / 2)
|
108
|
+
}
|
109
|
+
|
110
|
+
fb.put_column(rows, line)
|
111
|
+
line.clear
|
112
|
+
|
113
|
+
rows += 1
|
114
|
+
end
|
115
|
+
|
116
|
+
STDERR.printf(" ... done\n") if $verbose
|
117
|
+
|
118
|
+
STDERR.printf("write to #{output} ... ") if $verbose
|
119
|
+
|
120
|
+
draw_freq_line(fb) if $draw_freq_line
|
121
|
+
draw_time_line(fb, wav, usize) if $draw_time_line
|
122
|
+
|
123
|
+
png = PNG.encode(fb.width, fb.height, fb.to_s, :pixel_format => :RGB)
|
124
|
+
IO.binwrite(output, png)
|
125
|
+
|
126
|
+
STDERR.printf("done\n") if $verbose
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
#
|
5
|
+
# Spectrum analyzer for WAV file
|
6
|
+
#
|
7
|
+
# Copyright (C) 2019 Hiroshi Kuwagata <kgt9221@gmail.com>
|
8
|
+
#
|
9
|
+
|
10
|
+
module WavSpectrumAnalyzer
|
11
|
+
module FFTApp
|
12
|
+
PRESET_TABLE = {
|
13
|
+
"default" => {
|
14
|
+
:unit_time => 10,
|
15
|
+
:fft_size => 16384,
|
16
|
+
:output_width => 240,
|
17
|
+
:window_function => :FLAT_TOP,
|
18
|
+
:scale_mode => :LOGSCALE,
|
19
|
+
:range => [200, 8000],
|
20
|
+
:col_step => 1,
|
21
|
+
},
|
22
|
+
|
23
|
+
"32k" => {
|
24
|
+
:unit_time => 5,
|
25
|
+
:fft_size => 32768,
|
26
|
+
:output_width => 360,
|
27
|
+
:window_function => :FLAT_TOP,
|
28
|
+
:scale_mode => :LOGSCALE,
|
29
|
+
:range => [200, 16000],
|
30
|
+
:col_step => 1,
|
31
|
+
},
|
32
|
+
|
33
|
+
"cd" => {
|
34
|
+
:unit_time => 5,
|
35
|
+
:fft_size => 32768,
|
36
|
+
:output_width => 480,
|
37
|
+
:window_function => :FLAT_TOP,
|
38
|
+
:scale_mode => :LOGSCALE,
|
39
|
+
:range => [50, 22000],
|
40
|
+
:col_step => 1,
|
41
|
+
},
|
42
|
+
|
43
|
+
"highreso" => {
|
44
|
+
:unit_time => 5,
|
45
|
+
:fft_size => 131072,
|
46
|
+
:window_function => :FLAT_TOP,
|
47
|
+
:output_width => 640,
|
48
|
+
:scale_mode => :LOGSCALE,
|
49
|
+
:range => [200, 32000],
|
50
|
+
:col_step => 1,
|
51
|
+
},
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
#
|
5
|
+
# Spectrum analyzer for WAV file
|
6
|
+
#
|
7
|
+
# Copyright (C) 2019 Hiroshi Kuwagata <kgt9221@gmail.com>
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'wav'
|
11
|
+
require 'png'
|
12
|
+
|
13
|
+
require 'wavspa/wavelet'
|
14
|
+
require 'wavspa/fb'
|
15
|
+
|
16
|
+
module WavSpectrumAnalyzer
|
17
|
+
module WaveLetApp
|
18
|
+
extend WavSpectrumAnalyzer::Common
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def load_param(param)
|
22
|
+
@unit_time = param[:unit_time]
|
23
|
+
@sigma = param[:sigma]
|
24
|
+
@ceil = param[:ceil]
|
25
|
+
@floor = param[:floor]
|
26
|
+
@tran_mode = param[:transform_mode]
|
27
|
+
@output_width = param[:output_width]
|
28
|
+
@logscale = (param[:scale_mode] == :LOGSCALE)
|
29
|
+
@scale_mode = param[:scale_mode]
|
30
|
+
@col_step = param[:col_step]
|
31
|
+
|
32
|
+
@freq_range = param[:range]
|
33
|
+
@lo_freq = @freq_range[0]
|
34
|
+
@hi_freq = @freq_range[1]
|
35
|
+
@freq_width = (@hi_freq - @lo_freq)
|
36
|
+
|
37
|
+
@log_step = (@hi_freq / @lo_freq) ** (1.0 / @output_width)
|
38
|
+
@log_base = Math.log(@log_step)
|
39
|
+
@basis_freq = 440.0
|
40
|
+
end
|
41
|
+
private :load_param
|
42
|
+
|
43
|
+
def main(input, param, output)
|
44
|
+
load_param(param)
|
45
|
+
|
46
|
+
wav = WavFile.open(input)
|
47
|
+
wl = Wavelet.new
|
48
|
+
|
49
|
+
wl.frequency = wav.sample_rate
|
50
|
+
wl.sigma = @sigma
|
51
|
+
wl.range = (@lo_freq .. @hi_freq)
|
52
|
+
wl.scale_mode = @scale_mode
|
53
|
+
wl.width = @output_width
|
54
|
+
|
55
|
+
wl.put_in("s%dle" % wav.sample_size, wav.read)
|
56
|
+
|
57
|
+
line = []
|
58
|
+
rows = 0
|
59
|
+
|
60
|
+
usize = (wav.sample_rate * @unit_time) / 1000
|
61
|
+
nblk = (wav.data_size / wav.block_size) / usize
|
62
|
+
|
63
|
+
fb = FrameBuffer.new(nblk,
|
64
|
+
@output_width,
|
65
|
+
:column_step => @col_step,
|
66
|
+
:margin_x => ($draw_freq_line)? 50:0,
|
67
|
+
:margin_y => ($draw_time_line)? 30:0)
|
68
|
+
|
69
|
+
if $verbose
|
70
|
+
STDERR.print <<~EOT
|
71
|
+
- input data
|
72
|
+
#{input}
|
73
|
+
data size: #{wav.data_size}
|
74
|
+
channel num: #{wav.channel_num}
|
75
|
+
sample rate: #{wav.sample_rate} Hz
|
76
|
+
sample size: #{wav.sample_size} bits
|
77
|
+
data rate: #{wav.bytes_per_sec} bytes/sec
|
78
|
+
|
79
|
+
- FFT parameter
|
80
|
+
sigma: #{@sigma}
|
81
|
+
unit time: #{@unit_time} ms
|
82
|
+
ceil: #{@ceil}
|
83
|
+
floor: #{@floor}
|
84
|
+
mode : #{@tran_mode}
|
85
|
+
|
86
|
+
- OUTPUT
|
87
|
+
width: #{fb.width}px
|
88
|
+
height: #{fb.height}px
|
89
|
+
freq range: #{@lo_freq} - #{@hi_freq}Hz
|
90
|
+
scale mode: #{@scale_mode}
|
91
|
+
|
92
|
+
EOT
|
93
|
+
end
|
94
|
+
|
95
|
+
if wav.channel_num >= 2
|
96
|
+
STDERR.print("error: multi chanel data is not supported " \
|
97
|
+
"(support only monoral data).\n")
|
98
|
+
exit(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
until rows >= nblk
|
102
|
+
STDERR.printf("\rtransform #{rows + 1}/#{nblk}", rows) if $verbose
|
103
|
+
wl.transform(rows * usize)
|
104
|
+
|
105
|
+
result = (@transform_mode == :POWER)? wl.power: wl.amplitude
|
106
|
+
|
107
|
+
result.unpack("d*").each {|x|
|
108
|
+
if x > @ceil
|
109
|
+
x = 255
|
110
|
+
elsif x < @floor
|
111
|
+
x = 0
|
112
|
+
else
|
113
|
+
x = ((255 * (x - @floor)) / (@ceil - @floor)).floor
|
114
|
+
end
|
115
|
+
|
116
|
+
line.unshift(x / 3, x, x / 2)
|
117
|
+
}
|
118
|
+
|
119
|
+
fb.put_column(rows, line)
|
120
|
+
line.clear
|
121
|
+
|
122
|
+
rows += 1
|
123
|
+
end
|
124
|
+
|
125
|
+
STDERR.printf(" ... done\n") if $verbose
|
126
|
+
|
127
|
+
STDERR.printf("write to #{output} ... ") if $verbose
|
128
|
+
|
129
|
+
draw_freq_line(fb) if $draw_freq_line
|
130
|
+
draw_time_line(fb, wav, usize) if $draw_time_line
|
131
|
+
|
132
|
+
png = PNG.encode(fb.width, fb.height, fb.to_s, :pixel_format => :RGB)
|
133
|
+
IO.binwrite(output, png)
|
134
|
+
|
135
|
+
STDERR.printf("done\n") if $verbose
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
#
|
5
|
+
# Spectrum analyzer for WAV file
|
6
|
+
#
|
7
|
+
# Copyright (C) 2019 Hiroshi Kuwagata <kgt9221@gmail.com>
|
8
|
+
#
|
9
|
+
|
10
|
+
module WavSpectrumAnalyzer
|
11
|
+
module WaveLetApp
|
12
|
+
PRESET_TABLE = {
|
13
|
+
"default" => {
|
14
|
+
:sigma => 24.0,
|
15
|
+
:unit_time => 10 * 10,
|
16
|
+
:scale_mode => :LOGSCALE,
|
17
|
+
:transform_mode => :POWER,
|
18
|
+
:output_width => 240,
|
19
|
+
:range => [200.0, 8000.0],
|
20
|
+
:ceil => -10,
|
21
|
+
:floor => -90,
|
22
|
+
:col_step => 1,
|
23
|
+
},
|
24
|
+
|
25
|
+
"cd" => {
|
26
|
+
:sigma => 24.0,
|
27
|
+
:unit_time => 5 * 10,
|
28
|
+
:scale_mode => :LOGSCALE,
|
29
|
+
:transform_mode => :POWER,
|
30
|
+
:output_width => 480,
|
31
|
+
:range => [50.0, 22050.0],
|
32
|
+
:ceil => -10,
|
33
|
+
:floor => -90,
|
34
|
+
:col_step => 1,
|
35
|
+
},
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
data/wavspa.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "wavspa/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "wavspa"
|
8
|
+
spec.version = WavSpectrumAnalyzer::VERSION
|
9
|
+
spec.authors = ["Hirosho Kuwagata"]
|
10
|
+
spec.email = ["kgt9221@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{spectrum analyzer for wav file.}
|
13
|
+
spec.description = %q{spectrum analyzer for wav file.}
|
14
|
+
spec.homepage = "https://github.com/kwgt/wavspa"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
if spec.respond_to?(:metadata)
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
else
|
20
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
21
|
+
"public gem pushes."
|
22
|
+
end
|
23
|
+
|
24
|
+
# Specify which files should be added to the gem when it is released.
|
25
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been
|
26
|
+
# added into git.
|
27
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
28
|
+
`git ls-files -z`.split("\x0").reject { |f|
|
29
|
+
f.match(%r{^(test|spec|features)/})
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
spec.bindir = "bin"
|
34
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
35
|
+
spec.require_paths = ["none"]
|
36
|
+
spec.extensions = %w[
|
37
|
+
ext/wavspa/fft/extconf.rb
|
38
|
+
ext/wavspa/wavelet/extconf.rb
|
39
|
+
ext/wavspa/fb/extconf.rb
|
40
|
+
]
|
41
|
+
|
42
|
+
spec.required_ruby_version = ">= 2.4.0"
|
43
|
+
|
44
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
45
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
46
|
+
spec.add_dependency "libpng-ruby", "~> 0.5.2"
|
47
|
+
end
|