@@ -11,18 +11,22 @@ const MP3_BLOCKFRAMES = 1152
11
11
# max size needed to hold the encoded mp3 data for a full block
12
12
const MP3_BUFBYTES = ceil (Int, 1.25 * MP3_BLOCKFRAMES + 7200 )
13
13
14
- type MP3FileSink <: SampleSink
14
+ mutable struct MP3FileSink <: SampleSink
15
15
lame:: LAME
16
- info:: MP3INFO
16
+ samplerate:: Int
17
+ nchannels:: Int
17
18
output:: IO
19
+ nframes:: Int
18
20
mp3buf:: Vector{UInt8}
21
+ end
19
22
20
- MP3FileSink (lame, info, output) = new (lame, info, output, Array (UInt8, MP3_BUFBYTES))
23
+ function MP3FileSink (lame, samplerate, nchannels, output)
24
+ MP3FileSink (lame, samplerate, nchannels, output, 0 , Array {UInt8} (MP3_BUFBYTES))
21
25
end
22
26
23
- @inline nchannels (sink:: MP3FileSink ) = Int ( sink. info . nchannels)
24
- @inline samplerate (sink:: MP3FileSink ) = quantity (Int, Hz)( sink. info . samplerate)
25
- @inline nframes (sink:: MP3FileSink ) = sink. info . nframes
27
+ @inline nchannels (sink:: MP3FileSink ) = sink. nchannels
28
+ @inline samplerate (sink:: MP3FileSink ) = sink. samplerate
29
+ @inline nframes (sink:: MP3FileSink ) = sink. nframes
26
30
@inline Base. eltype (sink:: MP3FileSink ) = PCM16Sample
27
31
28
32
"""
@@ -42,37 +46,13 @@ save an MP3 file, using parameters as specified
42
46
* others: ID3v2 tag items to be added
43
47
"""
44
48
function save (file:: File , buf:: SampleBuf ;
45
- nchannels:: Integer = - 1 ,
46
- samplerate:: Union{Integer, Hertz} = - 1 ,
47
- bitrate:: Integer = 320 ,
48
- VBR:: Bool = false ,
49
- quality:: Number = 4 ,
50
- title:: AbstractString = " " ,
51
- artist:: AbstractString = " " ,
52
- album:: AbstractString = " " ,
53
- year:: AbstractString = " " ,
54
- comment:: AbstractString = " " )
55
-
56
- stream = savestream (file, MP3INFO (buf);
57
- nchannels = nchannels,
58
- samplerate = samplerate,
59
- bitrate = bitrate,
60
- VBR = VBR,
61
- quality = quality,
62
- title = title,
63
- artist = artist,
64
- album = album,
65
- year = year,
66
- comment = comment)
67
-
68
- try
49
+ samplerate= SampledSignals. samplerate (buf), nchannels= SampledSignals. nchannels (buf),
50
+ kwargs... )
51
+ savestream (file; samplerate= samplerate, nchannels= nchannels, kwargs... ) do stream
69
52
frameswritten = write (stream, buf)
70
53
if frameswritten != nframes (buf)
71
54
error (" Only wrote $frameswritten frames, expected $(nframes (buf)) " )
72
55
end
73
- finally
74
- # make sure we close the file even if something goes wrong
75
- close (stream)
76
56
end
77
57
78
58
nothing
@@ -90,62 +70,46 @@ function savestream(f::Function, args...; kwargs...)
90
70
end
91
71
end
92
72
93
- function savestream (path:: File , info :: MP3INFO ;
94
- nchannels:: Integer = - 1 ,
95
- samplerate:: Union{Integer, Hertz} = - 1 ,
96
- bitrate:: Integer = 320 ,
97
- VBR:: Bool = false ,
98
- quality:: Number = 4 ,
99
- title:: AbstractString = " " ,
100
- artist:: AbstractString = " " ,
101
- album:: AbstractString = " " ,
102
- year:: AbstractString = " " ,
103
- comment:: AbstractString = " " )
73
+ function savestream (path:: File ;
74
+ nchannels = 2 ,
75
+ samplerate = 44100 ,
76
+ bitrate = 320 ,
77
+ VBR = false ,
78
+ quality = 4 ,
79
+ title = " " ,
80
+ artist = " " ,
81
+ album = " " ,
82
+ year = " " ,
83
+ comment = " " )
104
84
105
85
lame = lame_init ()
106
- lame_set_num_samples (lame, info. nframes)
86
+ # lame_set_num_samples(lame, info.nframes)
107
87
108
-
109
- # default to the source channels
110
- if nchannels < 0
111
- nchannels = info. nchannels
112
- end
113
88
if nchannels == 1
114
89
lame_set_num_channels (lame, 1 )
115
90
lame_set_mode (lame, LAME_MONO)
116
- info. nchannels = 1
117
91
elseif nchannels == 2
118
92
lame_set_num_channels (lame, 2 )
119
93
lame_set_mode (lame, LAME_JOINT_STEREO)
120
- info. nchannels = 2
121
94
else
122
95
error (" the output channels should be either mono (1) or stereo (2)" )
123
96
end
124
97
125
- # default to the source sample rate
126
- if typeof (samplerate) == Hertz
127
- samplerate = samplerate. val
128
- end
129
- if samplerate < 0
130
- samplerate = info. samplerate
131
- else
132
- info. samplerate = samplerate
133
- end
134
98
if ! (samplerate in [8000 , 11025 , 12000 , 16000 , 22050 , 24000 , 32000 , 44100 , 48000 ])
135
99
error (" sample rate $samplerate Hz is not supported" )
136
100
end
137
101
# resampling is handled by SampledSignals
138
- lame_set_in_samplerate (lame, samplerate)
139
- lame_set_out_samplerate (lame, samplerate)
102
+ lame_set_in_samplerate (lame, Int ( samplerate) )
103
+ lame_set_out_samplerate (lame, Int ( samplerate) )
140
104
141
105
if VBR == false
142
106
# CBR mode
143
- lame_set_brate (lame, bitrate)
144
- lame_set_quality (lame, quality)
107
+ lame_set_brate (lame, Int ( bitrate) )
108
+ lame_set_quality (lame, Int ( quality) )
145
109
else
146
110
# VBR mode
147
111
lame_set_VBR (lame)
148
- lame_set_VBR_quality (lame, quality)
112
+ lame_set_VBR_quality (lame, Int ( quality) )
149
113
end
150
114
151
115
id3tag_init (lame)
@@ -161,13 +125,13 @@ function savestream(path::File, info::MP3INFO;
161
125
lame_init_params (lame)
162
126
163
127
id3size = lame_get_id3v2_tag (lame, UInt8[], 0 )
164
- id3buffer = Array ( UInt8, id3size)
128
+ id3buffer = Array { UInt8} ( id3size)
165
129
lame_get_id3v2_tag (lame, id3buffer, id3size) == id3size || error (" failed to get ID3v2 buffer" )
166
130
167
131
output = open (filename (path), " w" )
168
132
write (output, id3buffer)
169
133
170
- MP3FileSink (lame, info , output)
134
+ MP3FileSink (lame, samplerate, nchannels , output)
171
135
end
172
136
173
137
function unsafe_write (sink:: MP3FileSink , buf:: Array , frameoffset, framecount)
@@ -185,23 +149,24 @@ function unsafe_write(sink::MP3FileSink, buf::Array, frameoffset, framecount)
185
149
186
150
written = 0
187
151
while written < framecount
188
- nsamples = min (MP3_BLOCKFRAMES, framecount - written)
152
+ nframes = min (MP3_BLOCKFRAMES, framecount - written)
189
153
l = left + written * encsize
190
154
r = right + written * encsize
191
- bytes = lame_encode_buffer! (lame, l, r, nsamples , mp3buf, MP3_BUFBYTES)
192
- Compat . unsafe_write (sink. output, mp3buf, bytes)
155
+ bytes = lame_encode_buffer! (lame, l, r, nframes , mp3buf, MP3_BUFBYTES)
156
+ Base . unsafe_write (sink. output, mp3buf, bytes)
193
157
194
- written += nsamples
158
+ written += nframes
195
159
end
196
160
161
+ sink. nframes += written
197
162
written
198
163
end
199
164
200
165
function Base. close (sink:: MP3FileSink )
201
166
if sink. lame != C_NULL
202
167
mp3buf = pointer (sink. mp3buf)
203
168
bytes = lame_encode_flush_nogap (sink. lame, mp3buf, MP3_BUFBYTES)
204
- Compat . unsafe_write (sink. output, mp3buf, bytes)
169
+ Base . unsafe_write (sink. output, mp3buf, bytes)
205
170
206
171
err = lame_close (sink. lame)
207
172
close (sink. output)
0 commit comments