好的...我来晚了5年...但是我只是为自己做了这个并想把解决方案分享出来!
我在matlab中写大型wav文件时也遇到了内存不足的问题。我通过编辑matlab wavwrite函数,使用memmap
从硬盘中提取数据而不是存储在RAM中的变量,并将其保存为新函数来解决此问题。这将为您节省很多麻烦,因为您无需担心从头编写wav文件时处理标题,也不需要任何外部应用程序。
1)键入edit wavwrite
以查看该函数的代码,然后将其另存为新函数。
2)我修改了wavwrite
函数中的y
变量,将其从包含wav数据的数组更改为包含指向硬盘上每个通道数据位置的字符串的单元格数组。当然,首先要使用fwrite
将wav数据存储在硬盘上。在函数开头,我将存储在y
中的文件位置转换为memmap变量,并定义通道和样本数量,如下所示:
替换这些行:
if ndims(y) > 2,
error(message('MATLAB:audiovideo:wavwrite:invalidInputFormat'));
end
if size(y,1)==1,
y = y(:);
end
[samples, channels] = size(y);
with this:
channels = length(y);
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变量作为全局变量读取,而不是将值传递给函数并占用您的RAM,然后您可以进行一些更改,例如:
替换写入wav数据的行:
如果(fwrite(fid,reshape(data',total_samples,1),dtype)~ = total_samples)
error(message('MATLAB:audiovideo:wavewrite:failedToWriteSamples'));
end
使用以下内容:
packetSize = 30*(5e5);
packets = ceil(samples/packetSize);
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变量中的数据复制到wav文件中。
4) 就是这样!您可以将其余的代码保留不变,因为它会为您编写头文件。以下是使用此函数编写大型双通道wav文件的示例:
wavwriteModified({'c:\wavFileinputCh1' 'c:\wavFileinputCh2'},44100,16,'c:\output2ChanWavFile');
我可以验证这种方法是可行的,因为我刚刚使用我的编辑过的wavwrite函数写了一个800mB的4通道wav文件,而对于我来说,Matlab通常会在写大于200mb的wav文件时抛出“内存不足”的错误。