wavspa 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|