如何创建和修改矩阵并将其传递给函数?

时间:2019-12-03 07:05:10

标签: matlab math matrix

我是MATLAB的初学者,在分配作业时面临很多问题。作业的目的是创造具有教授给我们的功能的音乐。我设法创建了一个非常简单的旋律,但我想解决更复杂的问题:我用MIDI写了一个简单的旋律,用文本编辑器将其打开,现在我有了音符的MIDI代码矩阵。

现在,第一步是将这些MIDI代码转换为频率:

我知道freq = 440*power(2, (midicode-69)/12)。我想创建一个包含通过此公式传递的MIDI代码的矢量/矩阵(从而获得一个包含频率的矩阵),而我似乎找不到解决方法。老师的教材几乎不存在,我的互联网搜索让我更加困惑。

下一步(也是最后一步?)是将这些代码传递到教师功能中。它称为newsound(f),并以频率f作为参数。然后,它通过将频率分量和其他实用程序一一相加来创建声音。

现在,我需要传递给MATLAB soundsc()函数的是newsound(f)矩阵S中所有各个频率的结果。 这就是我的意思,最让我感到困惑(我在数学上也不是那么出色,是的...)

假设f(i)是包含从MIDI转换的频率的矢量/矩阵。然后,S1xn大小的矩阵,1是列,n是频率量:S = (S1, S2, ..., Sn)表示S1 = newsound(f(1)),..., Sn = newsound(f(n))

我非常感谢您提供围绕这些矩阵进行游戏的帮助!

1 个答案:

答案 0 :(得分:2)

据我了解,每个“声音”可能有多个MIDI代码,每个“声音”中的MIDI代码的数量可能会有所不同。因此,包含您的“声音”的MIDI代码的文本文件midicodes.txt可能看起来像这样:

60 61 69
62 64
63 68 69 72

第一步是读取该文件的所有内容:

% Read MIDI codes from text file, get cell array of vectors with MIDI codes
fid = fopen('midicodes.txt');
midi_codes = textscan(fid, '%s', 'delimiter', '\n')
midi_codes = cellfun(@(line) str2num(line), midi_codes{1}, 'UniformOutput', false)
fclose(fid);

textscan将把整个行作为文本文件中的字符串(或更好的字符集)提供给我们(由于MIDI代码向量的长度不同,我们在这里需要cell arrays):

midi_codes =
{
  [1,1] =
  {
    [1,1] = 60 61 69
    [2,1] = 62 64
    [3,1] = 63 68 69 72
  }
}

然后,我们使用str2num将每个字符串(或更好的是:字符数组)行转换为数字向量。为了对单元格数组中的每个单元格执行此操作,我们使用cellfun方法。

midi_codes =
{
  [1,1] =
     60   61   69
  [2,1] =
     62   64
  [3,1] =
     63   68   69   72
}

现在,我们为频率计算设置一个anonymous function,并计算所有MIDI代码的频率:

% Anonymous function to convert (vectors of) MIDI codes to frequencies
freq = @(midicode) 440 * 2.^((midicode - 69) / 12);

% Calculate frequencies for all MIDI codes
frequencies = cellfun(freq, midi_codes, 'UniformOutput', false)

输出:

frequencies =
{
  [1,1] =
     261.63   277.18   440.00
  [2,1] =
     293.66   329.63
  [3,1] =
     311.13   415.30   440.00   523.25
}

现在,我们假设newsound函数实际上是根据频率矢量计算一些“声音”的。作为一个模型,我创建了这个newsound.m函数文件:

function out = newsound(freq)
  out = sum(sin(freq));
end

我们可以为每个MIDI代码/频率矢量创建实际的“声音”:

% Generate sounds for all frequencies 
sounds = cellfun(@newsound, frequencies, 'UniformOutput', true)

输出:

sounds =
   0.070850
  -0.759869
   1.628095

现在:

% Play sounds!?
soundsc(sounds);

如果文本文件的外观不同,例如,如果使用其他定界符,则需要调整输入阅读部分。如果所有MIDI代码向量的长度都相同,则还可以使用纯数字数组而不是单元格数组。

希望有帮助!


免责声明:已在Octave 5.1.0中进行了测试,但语法应与MATLAB完全兼容。如果没有,请报告任何错误,我将尝试尽快解决。


编辑:根据评论的要求,以下是完整脚本:

% Read MIDI codes from text file, get cell array of vectors with MIDI codes
fid = fopen('midicodes.txt');
midi_codes = textscan(fid, '%s', 'delimiter', '\n')
midi_codes = cellfun(@(line) str2num(line), midi_codes{1}, 'UniformOutput', false)
fclose(fid);

% Anonymous function to convert (vectors of) MIDI codes to frequencies
freq = @(midicode) 440 * 2.^((midicode - 69) / 12);

% Calculate frequencies for all MIDI codes
frequencies = cellfun(freq, midi_codes, 'UniformOutput', false)

% Generate sounds for all frequencies 
sounds = cellfun(@newsound, frequencies, 'UniformOutput', true)

% Play sounds!?
%soundsc(sounds);