音声データよりFFT​を計算し一部を抜き出​し順次保存する方法(​ワークスペースor csv)

音声データよりFFTを順次保存することができるようになりましたが、1-44100のデータすべてではなく10001~20000のデータを抜き取りcsvファイルだけではなくワークスペースに一つにまとめて保存する方法をご教授お願いします。(csvファイルをひとつずつ作成するのではなく、FFTの結果(10001~20000)を一つの変数に順次保存するイメージです)
今までのプログラムも添付させていただいてます。

 Accepted Answer

Atsushi Ueno
Atsushi Ueno on 15 Nov 2022
Edited: Atsushi Ueno on 15 Nov 2022
下記の様にyを一つの変数ではなくセル配列にすれば、ワークスペースに一つにまとめて保存する事が出来ます。
for ii = 1:n
% y = fft(w.*x(Fs*(ii-1)+1:Fs*ii));
y{ii} = fft(w.*x(Fs*(ii-1)+1:Fs*ii)); % yをセル配列にする
writematrix(y{ii},sprintf('fftsave_%03d.csv',ii))
end

8 Comments

一秀 近藤
一秀 近藤 on 16 Nov 2022
ご回答ありがとうございます。
わかりやすく参考になりました。ちなみにですがyのデータの10001~20000行のみを抽出し、保存するには、どのように行えばよろしいですか?簡単な質問で申し訳ございません。ご教授お願いいたします。
一秀 近藤
一秀 近藤 on 16 Nov 2022
また、このような状態になり実行できませんでした。説明のほどいただけるとありがたいです。
Atsushi Ueno
Atsushi Ueno on 16 Nov 2022
Edited: Atsushi Ueno on 16 Nov 2022
添付ファイル fftsave_1115.mlx の冒頭で使用した変数 y (整数型の行列) が残っていて、コードの後半で y を異なる目的でしかもセル配列としてアクセスしようとした為に発生しているエラーです。
私の方で動作確認する際に不要だった冒頭部分を削除してから実行した為、問題に気付きませんでした。「変数の再代入」は多くのコーディング規約でも推奨されない悪習慣で止めるべきです
%音声出力
[y,Fs] = audioread('10k-20k-10kloop.wav'); % ここで変数 y が誕生
player = audioplayer(y,Fs); % y はこれ以降のコードで使用されない(はずだった)
play(player);
... % 省略
for ii = 1:n
% y = fft(w.*x(Fs*(ii-1)+1:Fs*ii));
y{ii} = fft(w.*x(Fs*(ii-1)+1:Fs*ii));
% ここで y を異なる用途に、しかも行列ではなくセル配列としてアクセス⇒エラー
writematrix(y{ii},sprintf('fftsave_%03d.csv',ii))
end
またはこの例の様に、変数 y を使い終わった後 clear で削除すれば安心して他の用途に使えますね。
% 当該エラーの再現
NotCell = [1 2 3; 4 5 6; 7 8 9]; % NotCellはセル配列ではなく行列
NotCell(2,3) % 普通の括弧なら添え字やインデックスでアクセス出来る
ans = 6
NotCell{2,3} % セル配列にアクセスする為の中括弧で行列にアクセスするとエラー
Brace indexing is not supported for variables of this type.
>yのデータの10001~20000行のみを抽出し、保存するには、どのように行えばよろしいですか?
その意図を考えると、添付ファイル fftsave_1115.mlx のFs=10000にして、そうすると
出力のy{1}は10001~20000行
出力のy{2}は10001~20000行
出力のy{3}は20001~30000行...
となるので、セル配列yの2番目、y{2}を保存すれば良いです。
wavファイルに記録されたサンプルレートとは異なるレートで区切る意図ですよね?
writematrix(y{2},sprintf('fftsave_%03d.csv',ii))
一秀 近藤
一秀 近藤 on 17 Nov 2022
返信が遅くなりました。
まず一つ目の質問についての解答ありがとうございます。すごく丁寧に教えていただきわかりやすかったです。早速実行してみたのですが、
このように一つ一つのセルとなってしまうのですが、
①1×23のセルではなく44100×23の形で残せるようにしたいです。
②またこの中の44100ではなく10001~20000だけを抽出し10000×23のセルの形を作りたいと考えてます。
質問の仕方も悪く何度も何度も申し訳ございません。ご教授いただけると幸いです。
①についてですが cell2mat で解決できます
for ii = 1:23
C{ii} = rand(1e3,1);
end
size(C)
ans = 1×2
1 23
C1 = cell2mat(C);
size(C1)
ans = 1×2
1000 23
②については以下のように抽出すればいいです
C2 = C1(1:500,:); % 今回は500行分
size(C2)
ans = 1×2
500 23
このプログラムは必ず同じサイズ(44100)のベクトルが積み重なっていくので、セル配列にする必要は無かったですね。もちろんセル配列にしても良いですし、セル配列にした後から行列に変換する事も可能です。
①1×23のセルではなく44100×23の形で残せるようにしたいです。
②またこの中の44100ではなく10001~20000だけを抽出し10000×23のセルの形を作りたいと考えてます。
n = 23; Fs = 44100;
w = hamming(Fs);
x = rand(Fs*n,1); % サンプルデータ
for ii = 1:n
% y = fft(w.*x(Fs*(ii-1)+1:Fs*ii));
y(:,ii) = fft(w.*x(Fs*(ii-1)+1:Fs*ii)); % 44100行のベクトルを23列積み重ねる
writematrix(y(:,ii),sprintf('fftsave_%03d.csv',ii))
end
size(y)
ans = 1×2
44100 23
z = y(10001:20000,:); % 10001~20000行の全列を抽出
size(z)
ans = 1×2
10000 23
すいません。MATLAB Answersで回答を続けているとどうしても保守的というか、どんな入力パターンが来ても良い様な「柔軟な方法」を選ぶ癖が付いてしまってます。でもそれは言い訳で、プログラムをよく読んで行列にすべきかセル配列にすべきかを判断する必要がありますね。
一秀 近藤
一秀 近藤 on 21 Nov 2022
ご丁寧な回答ありがとうございます。ならびに返信が遅れてしまい申し訳ございません。
とてもわかりやすく参考になりました!また自分の知識不足で混乱させてしまいすいません!
また何卒宜しくお願い致します!

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!