-
Notifications
You must be signed in to change notification settings - Fork 0
/
mp3write.m
173 lines (145 loc) · 4.76 KB
/
mp3write.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
function mp3write(D,SR,NBITS,FILE,OPTIONS)
% MP3WRITE Write MP3 file by use of external binary
% MP3WRITE(Y,FS,NBITS,FILE) writes waveform data Y to mp3-encoded
% file FILE at sampling rate FS using bitdepth NBITS.
% The syntax exactly mirrors WAVWRITE. NBITS must be 16.
% MP3WRITE(Y,FS,FILE) assumes NBITS is 16
% MP3WRITE(Y,FILE) further assumes FS = 8000.
%
% MP3WRITE(..., OPTIONS) specifies additional compression control
% options as a string passed directly to the lame encoder
% program; default is '--quiet -h' for high-quality model.
%
% Example:
% To convert a wav file to mp3 (assuming the sample rate is
% supported):
% [Y,FS] = wavread('piano.wav');
% mp3write(Y,FS,'piano.mp3');
% To force lame to use 160 kbps (instead of default 128 kbps)
% with the default filename extension (mp3):
% mp3write(Y,FS,'piano','--quiet -h -b 160');
%
% Note: The actual mp3 encoding is done by an external binary,
% lame, which is available for multiple platforms. Usable
% binaries are available from:
% http://labrosa.ee.columbia.edu/matlab/mp3read.html
%
% Note: MP3WRITE will use the mex file popenw, if available, to
% open a pipe to the lame encoder. Otherwise, it will have to
% write a large temporary file, then execute lame on that file.
% popenw is available at:
% http://labrosa.ee.columbia.edu/matlab/popenrw.html
% This is a nice way to save large audio files as the
% incremental output of your code, but you'll have to adapt the
% central loop of this function (rather than using it directly).
%
% See also: mp3read, wavwrite, popenw.
% 2005-11-10 Original version
% 2007-02-04 Modified to exactly match wavwrite syntax, and to
% automatically find architecture-dependent binaries.
% 2007-07-26 Writing of stereo files via tmp file fixed (thx Yu-ching Lin)
%
% $Header: /Users/dpwe/matlab/columbiafns/RCS/mp3write.m,v 1.2 2007/07/26 15:09:16 dpwe Exp $
% find our baseline directory
[path] = fileparts(which('mp3write'));
% %%%%% Directory for temporary file (if needed)
% % Try to read from environment, or use /tmp if it exists, or use CWD
tmpdir = getenv('TMPDIR');
if isempty(tmpdir) || exist(tmpdir,'file')==0
tmpdir = '/tmp';
end
if exist(tmpdir,'file')==0
tmpdir = '';
end
% ensure it exists
%if length(tmpdir) > 0 && exist(tmpdir,'file')==0
% mkdir(tmpdir);
%end
%%%%%% Command to delete temporary file (if needed)
rmcmd = 'rm';
%%%%%% Location of the binary - attempt to choose automatically
%%%%%% (or edit to be hard-coded for your installation)
ext = lower(computer);
if ispc
ext = 'exe';
rmcmd = 'del';
end
lame = fullfile(path,['lame.',ext]);
%%%% Process input arguments
% Do we have NBITS?
mynargin = nargin;
if ischar(NBITS)
% NBITS is a string i.e. it's actually the filename
if mynargin > 3
OPTIONS = FILE;
end
FILE = NBITS;
NBITS = 16;
% it's as if NBITS had been specified...
mynargin = mynargin + 1;
end
if mynargin < 5
OPTIONS = '--quiet -h'; % -h means high-quality psych model
end
[nr, nc] = size(D);
if nc < nr
D = D';
[nr, nc] = size(D);
end
% Now rows are channels, cols are time frames (so interleaving is right)
%%%%% add extension if none (like wavread)
[path,file,ext] = fileparts(FILE);
if isempty(ext)
FILE = [FILE, '.mp3'];
end
nchan = nr;
nfrm = nc;
if nchan == 1
monostring = ' -m m';
else
monostring = '';
end
lameopts = [' ', OPTIONS, monostring, ' '];
%if exist('popenw') == 3
if length(which('popenw')) > 0
% We have the writable stream process extensions
cmd = ['"',lame,'"', lameopts, '-r -s ',num2str(SR),' - "',FILE,'"'];
p = popenw(cmd);
if p < 0
error(['Error running popen(',cmd,')']);
end
% We feed the audio to the encoder in blocks of <blksize> frames.
% By adapting this loop, you can create your own code to
% write a single, large, MP3 file one part at a time.
blksiz = 10000;
nrem = nfrm;
base = 0;
while nrem > 0
thistime = min(nrem, blksiz);
done = popenw(p,32767*D(:,base+(1:thistime)),'int16be');
nrem = nrem - thistime;
base = base + thistime;
%disp(['done=',num2str(done)]);
end
% Close pipe
popenw(p,[]);
else
disp('Warning: popenw not available, writing temporary file');
tmpfile = fullfile(tmpdir,['tmp',num2str(round(1000*rand(1))),'.wav']);
wavwrite(D',SR,tmpfile);
cmd = ['"',lame,'"', lameopts, '"',tmpfile, '" "', FILE, '"'];
mysystem(cmd);
% Delete tmp file
mysystem([rmcmd, ' "', tmpfile,'"']);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function w = mysystem(cmd)
% Run system command; report error; strip all but last line
[s,w] = system(cmd);
if s ~= 0
error(['unable to execute ',cmd,' (',w,')']);
end
% Keep just final line
w = w((1+max([0,findstr(w,10)])):end);
% Debug
%disp([cmd,' -> ','*',w,'*']);