C++ 建立音乐(音符)模型的最佳方法,可在特定时间快速搜索音符

C++ 建立音乐(音符)模型的最佳方法,可在特定时间快速搜索音符,c++,performance,loops,vector,C++,Performance,Loops,Vector,我正在开发一款iOS音乐应用程序(用C++编写),我的模型大致如下: --Song ----Track ----Track ------Pattern ------Pattern --------Note --------Note --------Note 因此基本上一首歌曲有多个音轨,音轨可以有多个模式,模式有多个注释。这些东西中的每一个都由一个类表示,除了歌曲对象之外,它们都存储在向量中 每个音符都有一个“frame”参数,这样我就可以计算何时播放音符。例如,如果我每秒有44100个样本,

我正在开发一款iOS音乐应用程序(用C++编写),我的模型大致如下:

--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
    ,必须将所有其他内容转换过来,它也会花费大量时间