1- abstract AbstractSampleBuf{T, N} <: AbstractArray{T, N}
1+ abstract type AbstractSampleBuf{T, N} <: AbstractArray{T, N} end
22
33"""
44Represents a multi-channel regularly-sampled buffer that stores its own sample
@@ -8,13 +8,13 @@ buffer will be an MxC matrix. So a 1-second stereo audio buffer sampled at
8844100Hz with 32-bit floating-point samples in the time domain would have the
99type SampleBuf{Float32, 2}.
1010"""
11- type SampleBuf{T, N} <: AbstractSampleBuf{T, N}
11+ mutable struct SampleBuf{T, N} <: AbstractSampleBuf{T, N}
1212 data:: Array{T, N}
1313 samplerate:: Float64
1414end
1515
1616# define constructor so conversion is applied to `sr`
17- SampleBuf {T, N} (arr:: Array{T, N} , sr:: Real ) = SampleBuf {T, N} (arr, sr)
17+ SampleBuf (arr:: Array{T, N} , sr:: Real ) where {T, N} = SampleBuf {T, N} (arr, sr)
1818
1919"""
2020Represents a multi-channel regularly-sampled buffer representing the frequency-
@@ -24,16 +24,16 @@ C-channel buffer will be an MxC matrix. So a 1-second stereo audio buffer
2424sampled at 44100Hz with 32-bit floating-point samples in the time domain would
2525have the type SampleBuf{Float32, 2}.
2626"""
27- type SpectrumBuf{T, N} <: AbstractSampleBuf{T, N}
27+ mutable struct SpectrumBuf{T, N} <: AbstractSampleBuf{T, N}
2828 data:: Array{T, N}
2929 samplerate:: Float64
3030end
3131
3232# define constructor so conversion is applied to `sr`
33- SpectrumBuf {T, N} (arr:: Array{T, N} , sr:: Real ) = SpectrumBuf {T, N} (arr, sr)
33+ SpectrumBuf (arr:: Array{T, N} , sr:: Real ) where {T, N} = SpectrumBuf {T, N} (arr, sr)
3434
35- SampleBuf (T:: Type , sr, dims... ) = SampleBuf (Array (T, dims... ), sr)
36- SpectrumBuf (T:: Type , sr, dims... ) = SpectrumBuf (Array (T, dims... ), sr)
35+ SampleBuf (T:: Type , sr, dims... ) = SampleBuf (Array {T} ( dims... ), sr)
36+ SpectrumBuf (T:: Type , sr, dims... ) = SpectrumBuf (Array {T} ( dims... ), sr)
3737SampleBuf (T:: Type , sr, len:: SecondsQuantity ) = SampleBuf (T, sr, round (Int, float (len)* sr))
3838SampleBuf (T:: Type , sr, len:: SecondsQuantity , ch) = SampleBuf (T, sr, round (Int, float (len)* sr), ch)
3939SpectrumBuf (T:: Type , sr, len:: HertzQuantity ) = SpectrumBuf (T, sr, round (Int, float (len)* sr))
@@ -46,8 +46,8 @@ SpectrumBuf(T::Type, sr, len::HertzQuantity, ch) = SpectrumBuf(T, sr, round(Int,
4646
4747# audio methods
4848samplerate (buf:: AbstractSampleBuf ) = buf. samplerate
49- nchannels {T} (buf:: AbstractSampleBuf{T, 2} ) = size (buf. data, 2 )
50- nchannels {T} (buf:: AbstractSampleBuf{T, 1} ) = 1
49+ nchannels (buf:: AbstractSampleBuf{T, 2} ) where {T} = size (buf. data, 2 )
50+ nchannels (buf:: AbstractSampleBuf{T, 1} ) where {T} = 1
5151nframes (buf:: AbstractSampleBuf ) = size (buf. data, 1 )
5252
5353function samplerate! (buf:: AbstractSampleBuf , sr)
@@ -62,54 +62,82 @@ nchannels(arr::AbstractArray) = size(arr, 2)
6262
6363# it's important to define Base.similar so that range-indexing returns the
6464# right type, instead of just a bare array
65- Base. similar {T} (buf:: SampleBuf , :: Type{T} , dims:: Dims ) = SampleBuf (Array (T, dims), samplerate (buf))
66- Base. similar {T} (buf:: SpectrumBuf , :: Type{T} , dims:: Dims ) = SpectrumBuf (Array (T, dims), samplerate (buf))
65+ Base. similar (buf:: SampleBuf , :: Type{T} , dims:: Dims ) where {T} = SampleBuf (Array {T} ( dims), samplerate (buf))
66+ Base. similar (buf:: SpectrumBuf , :: Type{T} , dims:: Dims ) where {T} = SpectrumBuf (Array {T} ( dims), samplerate (buf))
6767domain (buf:: AbstractSampleBuf ) = linspace (0.0 , (nframes (buf)- 1 )/ samplerate (buf), nframes (buf))
6868
6969# There's got to be a better way to define these functions, but the dispatch
7070# and broadcast behavior for AbstractArrays is complex and has subtle differences
7171# between Julia versions, so we basically just override functions here as they
7272# come up as problems
73- import Base: .* , + , ./ , - , * , /
73+ import Base: + , - , * , /
74+ import Base. broadcast
7475
76+ const ArrayIsh = Union{Array, SubArray, LinSpace, StepRangeLen}
7577for btype in (:SampleBuf , :SpectrumBuf )
76- for op in (:.* , :+ , :./ , :- )
77- @eval function $ (op)(A1:: $btype , A2:: $btype )
78+ # define non-broadcasting arithmetic
79+ for op in (:+ , :- )
80+ @eval function $op (A1:: $btype , A2:: $btype )
7881 if ! isapprox (samplerate (A1), samplerate (A2))
7982 error (" samplerate-converting arithmetic not supported yet" )
8083 end
81- $ btype ($ (op) (A1. data, A2. data), samplerate (A1))
84+ $ btype ($ op (A1. data, A2. data), samplerate (A1))
8285 end
83- @eval function $ (op) (A1:: $btype , A2:: Union{Array, SubArray, LinSpace} )
84- $ btype ($ (op) (A1. data, A2), samplerate (A1))
86+ @eval function $op (A1:: $btype , A2:: ArrayIsh )
87+ $ btype ($ op (A1. data, A2), samplerate (A1))
8588 end
86- @eval function $ (op) (A1:: Union{Array, SubArray, LinSpace} , A2:: $btype )
87- $ btype ($ (op) (A1, A2. data), samplerate (A2))
89+ @eval function $op (A1:: ArrayIsh , A2:: $btype )
90+ $ btype ($ op (A1, A2. data), samplerate (A2))
8891 end
8992 end
9093
91- for op in (:* , :/ )
92- @eval function $ (op)(A1:: $btype , a2:: Number )
93- $ btype ($ (op)(A1. data, a2), samplerate (A1))
94+ # define broadcasting application
95+ @eval function broadcast (op, A1:: $btype , A2:: $btype )
96+ if ! isapprox (samplerate (A1), samplerate (A2))
97+ error (" samplerate-converting arithmetic not supported yet" )
9498 end
95- @eval function $ (op)(a1:: Number , A2:: $btype )
96- $ btype ($ (op)(a1, A2. data), samplerate (A2))
99+ $ btype (broadcast (op, A1. data, A2. data), samplerate (A1))
100+ end
101+ @eval function broadcast (op, A1:: $btype , A2:: ArrayIsh )
102+ $ btype (broadcast (op, A1. data, A2), samplerate (A1))
103+ end
104+ @eval function broadcast (op, A1:: ArrayIsh , A2:: $btype )
105+ $ btype (broadcast (op, A1, A2. data), samplerate (A2))
106+ end
107+ @eval function broadcast (op, a1:: Number , A2:: $btype )
108+ $ btype (broadcast (op, a1, A2. data), samplerate (A2))
109+ end
110+ @eval function broadcast (op, A1:: $btype , a2:: Number )
111+ $ btype (broadcast (op, A1. data, a2), samplerate (A1))
112+ end
113+ @eval function broadcast (op, A1:: $btype )
114+ $ btype (broadcast (op, A1. data), samplerate (A1))
115+ end
116+
117+
118+ # define non-broadcast scalar arithmetic
119+ for op in (:+ , :- , :* , :/ )
120+ @eval function $op (A1:: $btype , a2:: Number )
121+ $ btype ($ op (A1. data, a2), samplerate (A1))
122+ end
123+ @eval function $op (a1:: Number , A2:: $btype )
124+ $ btype ($ op (a1, A2. data), samplerate (A2))
97125 end
98126 end
99127end
100128
101- typename {T, N} ( :: SampleBuf {T, N}) = " SampleBuf{$T , $N }"
129+ typename ( :: SampleBuf {T, N}) where {T, N} = " SampleBuf{$T , $N }"
102130unitname (:: SampleBuf ) = " s"
103131srname (:: SampleBuf ) = " Hz"
104- typename {T, N} ( :: SpectrumBuf {T, N}) = " SpectrumBuf{$T , $N }"
132+ typename ( :: SpectrumBuf {T, N}) where {T, N} = " SpectrumBuf{$T , $N }"
105133unitname (:: SpectrumBuf ) = " Hz"
106134srname (:: SpectrumBuf ) = " s"
107135
108136# from @mbauman's Sparklines.jl package
109137const ticks = [' ▁' ,' ▂' ,' ▃' ,' ▄' ,' ▅' ,' ▆' ,' ▇' ,' █' ]
110138# 3-arg version (with explicit mimetype) is needed because we subtype AbstractArray,
111139# and there's a 3-arg version defined in show.jl
112- @compat function show (io:: IO , :: MIME"text/plain" , buf:: AbstractSampleBuf )
140+ function show (io:: IO , :: MIME"text/plain" , buf:: AbstractSampleBuf )
113141 println (io, " $(nframes (buf)) -frame, $(nchannels (buf)) -channel $(typename (buf)) " )
114142 len = nframes (buf) / samplerate (buf)
115143 ustring = unitname (buf)
@@ -122,19 +150,19 @@ function showchannels(io::IO, buf::AbstractSampleBuf, widthchars=80)
122150 # number of samples per block
123151 blockwidth = round (Int, nframes (buf)/ widthchars, RoundUp)
124152 nblocks = round (Int, nframes (buf)/ blockwidth, RoundUp)
125- blocks = Array ( Char, nblocks, nchannels (buf))
153+ blocks = Array { Char} ( nblocks, nchannels (buf))
126154 for blk in 1 : nblocks
127155 i = (blk- 1 )* blockwidth + 1
128156 n = min (blockwidth, nframes (buf)- i+ 1 )
129- peaks = maximum (abs (float (buf[(1 : n)+ i- 1 , :])), 1 )
157+ peaks = maximum (abs . (float (buf[(1 : n)+ i- 1 , :])), 1 )
130158 # clamp to -60dB, 0dB
131- peaks = clamp (20 log10 (peaks), - 60.0 , 0.0 )
132- idxs = trunc (Int, (peaks+ 60 )/ 60 * (length (ticks)- 1 )) + 1
159+ peaks = clamp . (20 log10 . (peaks), - 60.0 , 0.0 )
160+ idxs = trunc . (Int, (peaks+ 60 )/ 60 * (length (ticks)- 1 )) + 1
133161 blocks[blk, :] = ticks[idxs]
134162 end
135163 for ch in 1 : nchannels (buf)
136164 println (io)
137- print (io, convert (UTF8String , blocks[:, ch]))
165+ print (io, convert (String , blocks[:, ch]))
138166 end
139167end
140168
@@ -221,18 +249,18 @@ end
221249
222250# the index types that Base knows how to handle. Separate out those that index
223251# multiple results
224- typealias BuiltinMultiIdx Union{Colon,
225- Vector{Int},
226- Vector{Bool},
227- Range{Int}}
228- typealias BuiltinIdx Union{Int, BuiltinMultiIdx}
252+ const BuiltinMultiIdx = Union{Colon,
253+ Vector{Int},
254+ Vector{Bool},
255+ Range{Int}}
256+ const BuiltinIdx = Union{Int, BuiltinMultiIdx}
229257# the index types that will need conversion to built-in index types. Each of
230258# these needs a `toindex` method defined for it
231- typealias ConvertIdx{T1 <: SIQuantity , T2 <: Int } Union{T1,
232- # Vector{T1}, # not supporting vectors of SIQuantities (yet?)
233- # Range{T1}, # not supporting ranges (yet?)
234- Interval{T2},
235- Interval{T1}}
259+ const ConvertIdx{T1 <: SIQuantity , T2 <: Int } = Union{T1,
260+ # Vector{T1}, # not supporting vectors of SIQuantities (yet?)
261+ # Range{T1}, # not supporting ranges (yet?)
262+ Interval{T2},
263+ Interval{T1}}
236264
237265"""
238266 toindex(buf::SampleBuf, I)
@@ -242,17 +270,17 @@ indexing
242270"""
243271function toindex end
244272
245- toindex {T <: Number, N} (buf:: SampleBuf{T, N} , t:: SecondsQuantity ) = round (Int, float (t)* samplerate (buf)) + 1
246- toindex {T <: Number, N} (buf:: SpectrumBuf{T, N} , t:: HertzQuantity ) = round (Int, float (t)* samplerate (buf)) + 1
273+ toindex (buf:: SampleBuf{T, N} , t:: SecondsQuantity ) where {T <: Number , N} = round (Int, float (t)* samplerate (buf)) + 1
274+ toindex (buf:: SpectrumBuf{T, N} , t:: HertzQuantity ) where {T <: Number , N} = round (Int, float (t)* samplerate (buf)) + 1
247275
248276# indexing by vectors of SIQuantities not yet supported
249277# toindex{T <: SIUnits.SIQuantity}(buf::SampleBuf, I::Vector{T}) = Int[toindex(buf, i) for i in I]
250278toindex (buf:: AbstractSampleBuf , I:: Interval{Int} ) = I. lo: I. hi
251- toindex {T <: SIQuantity} (buf:: AbstractSampleBuf , I:: Interval{T} ) = toindex (buf, I. lo): toindex (buf, I. hi)
279+ toindex (buf:: AbstractSampleBuf , I:: Interval{T} ) where {T <: SIQuantity } = toindex (buf, I. lo): toindex (buf, I. hi)
252280
253281# AbstractArray interface methods
254282Base. size (buf:: AbstractSampleBuf ) = size (buf. data)
255- Base. linearindexing {T <: AbstractSampleBuf} (:: Type{T} ) = Base. LinearFast ()
283+ Base. IndexStyle (:: Type{T} ) where {T <: AbstractSampleBuf } = Base. IndexLinear ()
256284# this is the fundamental indexing operation needed for the AbstractArray interface
257285Base. getindex (buf:: AbstractSampleBuf , i:: Int ) = buf. data[i];
258286
@@ -282,14 +310,14 @@ Base.ifft(buf::SpectrumBuf) = SampleBuf(ifft(buf.data), nframes(buf)/samplerate(
282310
283311# does a per-channel convolution on SampleBufs
284312for buftype in (:SampleBuf , :SpectrumBuf )
285- @eval function Base. conv {T} (b1:: $buftype{T, 1} , b2:: $buftype{T, 1} )
313+ @eval function Base. conv (b1:: $buftype{T, 1} , b2:: $buftype{T, 1} ) where {T}
286314 if ! isapprox (samplerate (b1), samplerate (b2))
287315 error (" Resampling convolution not yet supported" )
288316 end
289317 $ buftype (conv (b1. data, b2. data), samplerate (b1))
290318 end
291319
292- @eval function Base. conv {T, N1, N2} (b1:: $buftype{T, N1} , b2:: $buftype{T, N2} )
320+ @eval function Base. conv (b1:: $buftype{T, N1} , b2:: $buftype{T, N2} ) where {T, N1, N2}
293321 if ! isapprox (samplerate (b1), samplerate (b2))
294322 error (" Resampling convolution not yet supported" )
295323 end
@@ -304,13 +332,13 @@ for buftype in (:SampleBuf, :SpectrumBuf)
304332 out
305333 end
306334
307- @eval function Base. conv {T} (b1:: $buftype{T, 1} , b2:: StridedVector{T} )
335+ @eval function Base. conv (b1:: $buftype{T, 1} , b2:: StridedVector{T} ) where {T}
308336 $ buftype (conv (b1. data, b2), samplerate (b1))
309337 end
310338
311- @eval Base. conv {T} (b1:: StridedVector{T} , b2:: $buftype{T, 1} ) = conv (b2, b1)
339+ @eval Base. conv (b1:: StridedVector{T} , b2:: $buftype{T, 1} ) where {T} = conv (b2, b1)
312340
313- @eval function Base. conv {T} (b1:: $buftype{T, 2} , b2:: StridedMatrix{T} )
341+ @eval function Base. conv (b1:: $buftype{T, 2} , b2:: StridedMatrix{T} ) where {T}
314342 if nchannels (b1) != nchannels (b2)
315343 error (" Broadcasting convolution not yet supported" )
316344 end
@@ -322,5 +350,5 @@ for buftype in (:SampleBuf, :SpectrumBuf)
322350 out
323351 end
324352
325- @eval Base. conv {T} (b1:: StridedMatrix{T} , b2:: $buftype{T, 2} ) = conv (b2, b1)
353+ @eval Base. conv (b1:: StridedMatrix{T} , b2:: $buftype{T, 2} ) where {T} = conv (b2, b1)
326354end
0 commit comments