首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >由于内存限制,将向量循环转换为for循环

由于内存限制,将向量循环转换为for循环
EN

Stack Overflow用户
提问于 2015-04-03 16:39:22
回答 1查看 136关注 0票数 1

我有一段Octave / Matlab代码,我从Andy和大家那里得到了很多帮助。我现在遇到的问题是内存不足,无法发出持续时间较长的信号。

我的计划是:

1)将向量循环转换为for循环。(这里有问题)

2)让for循环将循环的每个部分导出为wav文件,而不是执行附加向量代码所做的操作。(这里有问题)

3)使用sox连接各波形文件段。

大多数在线示例从for循环转到向量化循环,而不是相反,有什么想法吗?我也愿意接受其他建议来解决我的记忆问题。注意:我正在一个rasberry pi 2上使用1G的ram,它工作得非常快,我只是想获得一个更长的持续时间的信号,导出每个片段应该允许这样做。

我使用的是Octave,它与Matlab兼容。

请参阅下面的工作矢量化代码:它基于Paul的拉伸算法,在这里可以找到http://www.paulnasca.com/algorithms-created-by-me#TOC-PaulStretch-extreme-sound-stretching-algorithm

代码语言:javascript
复制
urlwrite('http://www.onewithall.net/rttmpfiles/3sec8000.wav','3sec8000.wav'); 
inputfn='3sec8000.wav' %change this to test another file
[d, fs, bps]=wavread(inputfn);
inputlen=rows  (d)/fs;

printf ("Original duration of file in seconds = %.2f s\n", rows (d)/fs);

dur=60; %duration / length you want the file to be in seconds
stretch = dur/rows(d)*fs; %how much I need to stretch the file to get it to be the duration I want
windowsize = round (0.25 * fs);

step = round ((windowsize/2)/stretch);

## original window
fwin = @(x) (1-x.^2).^1.25;
win = fwin (linspace (-1, 1, windowsize));

#win = hanning (windowsize)';

## build index
ind = (bsxfun (@plus, 1:windowsize, (0:step:(rows(d)-windowsize))'))';
cols_ind = columns(ind);

## Only use left channel
left_seg = d(:,1)(ind);
clear d ind;

## Apply window
left_seg = bsxfun (@times, left_seg, win');

## FFT
fft_left_seg = fft (left_seg);
clear left_seg

#keyboard

## overwrite phases with random phases
fft_rand_phase_left = fft_left_seg.*exp(i*2*pi*rand(size(fft_left_seg)));
clear fft_left_seg;

ifft_left = ifft (fft_rand_phase_left);
clear fft_rand_phase_left;

## window again
ifft_left = bsxfun (@times, real(ifft_left), win');

## restore the windowed segments with half windowsize shift
restore_step = floor(windowsize/2);
ind2 = (bsxfun (@plus, 1:windowsize, (0:restore_step:(restore_step*(cols_ind-1)))'))';
left_stretched = sparse (ind2(:), repmat(1:columns (ind2), rows(ind2), 1)(:), real(ifft_left(:)), ind2(end, end), cols_ind);
clear ind2 ifft_left win;

left_stretched = full (sum (left_stretched, 2));

## normalize
left_stretched = 0.8 * left_stretched./max(left_stretched);
printf ("converted %s =%.2f(s) file to stretched.wav = %.2f(s)\n", inputfn, inputlen, rows (left_stretched)/fs);
wavwrite (left_stretched, fs, bps, "streched.wav");

我试图通过在关键点上显示(行)来追踪这个问题。看上去就像这条线

代码语言:javascript
复制
left_stretched = sparse (ind2(:), repmat(1:columns (ind2), rows(ind2), 1)(:), real(ifft_left(:)), ind2(end, end), cols_ind);

上面的一行似乎只有当我用完内存时才有问题。它说错误下标指数必须是正整数或逻辑。请注意,只有当我试图通过设置dur=60*1800来使用长时间的内存时,才会出现这种情况。如果我设置了dur=60*10,一切都会正常工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-05 21:42:51

你还记得我吗?我是你发布的初始代码的作者。在代码下面作为循环。我已经用800秒的输出连测试过这个。

代码语言:javascript
复制
## based on http://hypermammut.sourceforge.net/paulstretch/
## https://github.com/paulnasca/paulstretch_python/blob/master/paulstretch_steps.png

more off
inputfn = "original.wav"
[d, fs, bps] = wavread (inputfn);
inputlen=rows  (d)/fs;

printf ("Original  duration of file in seconds = %.2f s\n", rows (d)/fs);

target_duration = 60; # in seconds
stretch = target_duration/inputlen;
# 1/4 s window len
windowsize = round (0.25 * fs);

# stepwidth between windows
step = round ((windowsize/2)/stretch);
numsteps = floor((rows(d)-windowsize)/step);

## restore the windowed segments with half windowsize shift
restore_step = floor (windowsize / 2);

## stetched duration
stretched_len = (numsteps*restore_step+windowsize)/fs;
printf ("Stretched duration of file in seconds = %.2f s\n", stretched_len);
stretched = zeros (numsteps*restore_step+windowsize, 1);
if (!exist ("out", "dir"))
  mkdir ("out");
endif

## Matrix which holds the freq of the maximum amplitude and the max. amplitude
chunks_stats = zeros (numsteps, 2);

## original window
fwin = @(x) (1-x.^2).^1.25;
win = fwin (linspace (-1, 1, windowsize));

## loop over all windows
for k = 1:numsteps
  if (! mod(k, 50))
    printf ("Calculating chunk %i of %i...\n", k, numsteps);
    fflush (stdout);
  endif

  ## Only use left channel
  s_ind = (k - 1) * step + 1;
  e_ind = s_ind + windowsize - 1;
  tmp = win' .* d(s_ind:e_ind, 1);

  ## FFT, overwrite phases with random phases and IFFT
  tmp = fft(tmp);
  [m, ind] = max (abs(tmp(1:numel(tmp)/2)));
  # Frequency in Hz
  chunks_stats(k, 1) = (ind-1)/windowsize*fs;
  # max Amplitude
  chunks_stats(k, 2) = m;
  printf ("Freq =  %.2f Hz, max = %.2f\n", chunks_stats(k, :));
  tmp = ifft (tmp .* exp(i*2*pi*rand(size(tmp))));

  ## window again
  tmp = win' .* real (tmp);
  fn = sprintf ("out/out_%04i.wav", k);
  wavwrite (tmp, fs, bps, fn);
  s_ind = (k - 1) * restore_step + 1;
  e_ind = s_ind + windowsize - 1;
  stretched (s_ind:e_ind) += tmp;
endfor

## normalize
stretched = 0.8 * stretched./max(stretched);
wavwrite (stretched, fs, bps, "stretched.wav");

如果您想要编写多个wavs来连接它们,那么比较困难一些,因为重叠的窗口。但是我认为这段代码在BeagleBoneBlack上运行的很好。

编辑:添加保存块到单独的文件,并收集这个信号的最大幅度和频率的每个块到chunk_stats。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29436182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档