C++ 建立音乐(音符)模型的最佳方法,可在特定时间快速搜索音符
我正在开发一款iOS音乐应用程序(用C++编写),我的模型大致如下:C++ 建立音乐(音符)模型的最佳方法,可在特定时间快速搜索音符,c++,performance,loops,vector,C++,Performance,Loops,Vector,我正在开发一款iOS音乐应用程序(用C++编写),我的模型大致如下: --Song ----Track ----Track ------Pattern ------Pattern --------Note --------Note --------Note 因此基本上一首歌曲有多个音轨,音轨可以有多个模式,模式有多个注释。这些东西中的每一个都由一个类表示,除了歌曲对象之外,它们都存储在向量中 每个音符都有一个“frame”参数,这样我就可以计算何时播放音符。例如,如果我每秒有44100个样本,
--Song
----Track
----Track
------Pattern
------Pattern
--------Note
--------Note
--------Note
因此基本上一首歌曲有多个音轨
,音轨
可以有多个模式
,模式
有多个注释。
这些东西中的每一个都由一个类表示,除了歌曲对象之外,它们都存储在向量中
每个音符
都有一个“frame”
参数,这样我就可以计算何时播放音符。例如,如果我每秒有44100个样本,并且一个特定注释的帧是132300,我知道我需要在第三秒开始时使用该注释
我的问题是,我应该如何表达这些注释以获得最佳性能?现在我正在考虑将音符存储在每个模式的向量数据成员中,然后循环所有歌曲的音轨,然后查看模式并循环音符,以查看哪个帧数据成员大于132300小于176400(从第4秒开始)
正如你所知,这是一个循环,一首歌可能长达10分钟。所以我想知道这是否足够快,可以计算出所有的帧,并及时将它们发送到缓冲区
我的模型大致如下:
--Song
----Track
----Track
------Pattern
------Pattern
--------Note
--------Note
--------Note
您的模型中缺少几个至关重要的概念:
节奏
仪器
(可选)音调
效果(混响/合唱、俯仰轮)
立体定位
歌词
和弦贴图
作曲家信息/标题
每个音符都有一个“frame”参数,这样我就可以计算何时播放音符
您的模型中缺少几个至关重要的概念:
发音
后触摸
注意持续时间
我建议你去看看。这是排版软件,但它也是以人类可读的文本格式表达音乐的最精确方式之一
我的问题是,我应该如何表达这些注释以获得最佳性能
将它们全部放入std::map
中,并使用下限/上限查找要播放的片段。或者,只要对数据进行排序,就可以在平面std::vector中对它们进行二进制搜索
除非你想制作一个“传呼机”,否则制作音乐应用程序比你想象的要困难得多。我强烈建议您尝试另一个项目。您应该记住的一件事是,为了提高性能,通常必须增加内存消耗。在这种情况下,它也是相关的(并且是合理的),因为我相信您希望以不同的方式将相同的数据存储两次
首先,你应该有一首歌的基本结构:
map<Track, vector<Pattern>> tracks;
出于性能考虑,您可以使用第二种方式存储笔记:
map<int, vector<Notes>> measures;
map度量;
这一个将把模式中的每个度量值(按其编号)映射到该度量值中包含的注释的向量。每次主注释
存储中的数据发生更改时,您都会对度量
中的数据应用相同的更改。您也可以在每次播放之前,甚至在播放时,在单独的线程中只执行一次
当然,您只能在度量中存储注释,而不必同步两个数据源。但是,当您必须对一串音符应用大规模操作时,使用它可能不太方便
在播放过程中,在下一次测量开始之前,将发生以下算法(大致):
在每一个轨迹中,找到所有的模式,pattern->startTime只需对这些向量进行排序即可
在播放过程中,您只需在最后一个音符播放器的每个向量中保留一个指针(索引)。要搜索新的注释,您必须在每个向量中检查以下注释,不需要循环注释。将向量排序,然后进行尝试-这更重要,您可以在此处收到任何答案
对于你的所有问题,你应该先通过测试和原型来回答,然后你就会知道你是否有问题。此外,在尝试时,您会看到一些仅凭理论通常无法看到的东西。“我的问题是,我应该如何表示这些注释以获得最佳性能?”这取决于您将如何处理数据。好的,请选中以下框:[。]“我正在重新创建MOD文件”
或[。]“我正在重新设计MIDI文件“
。请注意,这是一个学校项目,我怀疑他们会对这个答案感到满意。老实说,我不明白这有什么关系……你只是假设我在复制已经存在的东西,而我知道事实并非如此。这些日子很难有100%个原创,但这并不是制作一个好产品的必要。@ SigTeSle正在询问如何使用C++的标准容器在内存中存储数据。MIDI和MOD是用于在磁盘上存储相同数据的二进制格式,它们与优化性能和实际播放存储在其中的音乐无关。实际上,我已经实现了您提到的大部分内容。不是所有的,因为有些我不需要(踏板、效果、歌词和和弦),我强烈建议不要使用std::list
。数据局部性通常是性能最重要的部分,而std::list
会破坏这一点。我从未在自己的代码中发现过这样的情况,即std::list
比std::vector
或std::deque
性能更好。即使您偶尔插入到中间,并且担心如果您使用std::vector
,必须将所有其他内容转换过来,它也会花费大量时间