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