Хорошо ... Я опоздал на 5 лет ... но я просто сделал это для себя и хотел найти решение!
У меня была такая же проблема с нехваткой памяти при записи больших файлов WAV в Matlab. Я справился с этим, отредактировав функцию matlab wavwrite так, чтобы она извлекала данные с вашего жесткого диска, используя memmap
вместо переменных, хранящихся в ОЗУ, а затем сохраняла их как новую функцию. Это избавит вас от многих проблем, так как вам не нужно беспокоиться о работе с заголовками при написании wav-файла с нуля, и вам не понадобятся внешние приложения.
1) введите edit wavwrite
, чтобы увидеть код функции, а затем сохраните ее копию в качестве новой функции.
2) Я изменил переменную y
в функции wavwrite
из массива, содержащего данные wav, в массив ячеек со строками, указывающими места для данных каждого канала, сохраненных на моем жестком диске. Используйте fwrite
для сохранения ваших wav-данных на жестком диске. В начале функции я преобразовал расположение файлов, хранящихся в y
, в переменные memmap и определил количество каналов и сэмплов следующим образом:
заменить эти строки:
% If input is a vector, force it to be a column:
if ndims(y) > 2,
error(message('MATLAB:audiovideo:wavwrite:invalidInputFormat'));
end
if size(y,1)==1,
y = y(:);
end
[samples, channels] = size(y);
с этим:
% get num of channels
channels = length(y);
%Convert y from strings pointing to wav data to mammap variables allowing access to the data
for i = 1:length(y)
y{i} = memmapfile(y{i},'Writable',false,'Format','int16');
end
samples = length(y{1}.Data);
3) Теперь вы можете редактировать приватную функцию write_wavedat(fid,fmt)
. Это функция, которая записывает данные WAV. Превратите его во вложенную функцию, чтобы она могла читать вашу переменную y
memmap как глобальную переменную, вместо того, чтобы передавать значение в функцию и поглощать вашу оперативную память, тогда вы можете внести некоторые изменения, например:
заменить строки, которые записывают данные WAV:
if (fwrite(fid, reshape(data',total_samples,1), dtype) ~= total_samples),
error(message('MATLAB:audiovideo:wavewrite:failedToWriteSamples'));
end
с этим:
%Divide data into smaller packets for writing
packetSize = 30*(5e5); %n*5e5 = n Mb of space required
packets = ceil(samples/packetSize);
% Write data to file!
for i=1:length(y)
for j=1:packets
if j == packets
fwrite(fid, y{i}.Data(((j-1)*packetSize)+1:end), dtype);
else
fwrite(fid, y{i}.Data(((j-1)*packetSize)+1:j*packetSize), dtype);
end
disp(['...' num2str(floor(100*((i-1)*packets + j)/(packets*channels))) '% done writing file...']);
end
end
Это будет постепенно копировать данные из каждой переменной memmap в wavfile
4) Так и должно быть! Вы можете оставить остальную часть кода как есть, так как он напишет заголовки для вас. Вот пример того, как вы могли бы написать большой 2-канальный WAV-файл с помощью этой функции:
wavwriteModified({'c:\wavFileinputCh1' 'c:\wavFileinputCh2'},44100,16,'c:\output2ChanWavFile');
Я могу убедиться, что этот подход работает, так как я только что написал 4-канальный wav-файл 800 МБ с моей отредактированной функцией wavwrite, когда matlab обычно выдает ошибку out of memmory
при записи wav-файлов размером более 200 МБ для меня.