如何在java中创建一个简单但结构良好的乐谱表(乐谱)?

前端之家收集整理的这篇文章主要介绍了如何在java中创建一个简单但结构良好的乐谱表(乐谱)?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用非常基本的声音合成在我的游戏中创建音频和效果.基本上,我有一些方法可以发出一个频率和频率的声音.幅度和幅度持续时间.

对于短语和旋律,我想提出一个基本的符号,这样我就可以轻松地重写或添加新的旋律到代码中(最后也许我可以从文件中读取,但这可能是矫枉过正的).

我不知道如何实现这一点.

我首先创建了一个枚举EqualTemperamentTuning,其中包含所有88个带有MIDI#字段和频率字段的基本钢琴音符.这至少意味着我可以处理音符名称而不是频率.

  1. public enum EqualTemperamentTuning {
  2. A_0 (1,27.5),A_SHARP_0 (2,29.1352),...
  3. C_8 (88,4186.01);
  4.  
  5. private int num;
  6. private double frequency;
  7.  
  8. EqualTemperamentTuning(int num,double frequency){
  9.  
  10. this.num = num;
  11. this.frequency = frequency;
  12. }
  13.  
  14. public double getFrequency(){
  15. return frequency;
  16. }
  17.  
  18. public double getNum(){
  19. return num;
  20. }
  21. }

然后我开始创建更多的对象,首先是一个Note,它包含EqualTemperamentTuning,一个幅度和一个长度:

  1. public class Note {
  2.  
  3. /** Note frequency */
  4. private double frequency;
  5. /** Note Amplitude */
  6. private double amplitude;
  7. /** Note length */
  8. private int length;
  9.  
  10. public Note(EqualTemperamentTuning tuning,double amplitude,int length){
  11.  
  12. this.frequency = tuning.getFrequency();
  13. this.amplitude = amplitude;
  14. this.length = length;
  15. }
  16.  
  17. public double getFrequency(){
  18. return frequency;
  19. }
  20.  
  21. public double getAmplitude(){
  22. return amplitude;
  23. }
  24.  
  25. public int getLength(){
  26. return length;
  27. }
  28. }

最后为了定义我想要播放的旋律,我创建了一个NotePhrase类:

  1. public class NotePhrase {
  2.  
  3. /** The arrayList of notes*/
  4. private Note[] notes;
  5.  
  6. public NotePhrase(Note[] notes){
  7.  
  8. this.notes = notes;
  9. }
  10.  
  11. public double getFrequency(int counter){
  12.  
  13. // for each note in the array
  14. for (int i = 0; i< notes.length; i++){
  15.  
  16. // for each unit of length per note
  17. for (int j=0; j<notes[i].getLength(); j++){
  18.  
  19. counter--;
  20.  
  21. // return the frequency at this point
  22. if (counter <= 0) return notes[i].getFrequency();
  23.  
  24. }
  25. }
  26. return -1;
  27. }
  28. }

然后在我的音频生成类中,我有一个循环(带计数器),它从波形发生器生成样本.每次我需要播放一个新样本时,它会根据上面的NotePhrase.getFrequency(int counter)方法设置wave的频率.这应该(我还没有真正测试过!)只是根据频率和幅度播放NotePhrase旋律(待添加).

问题是,它看起来并不优雅,更具体地说,以任何一种清晰的方式“写”旋律是非常困难的.我必须编写一大堆新的Note对象,然后使用它们的数组构造一个NotePhrase对象……对我来说,如何硬编码这些旋律然后在之后轻松切换它们并不明显.

我真的想创建一个Melodies或类似的东西,我可以轻松地为每个不同的旋律硬编码人类易读的配置,然后当我想使用它们时,只需将枚举类型传递给音频播放器. .

我得到的最好的是:

  1. private static enum Melody {
  2. NOKIA_RINGTONE ( new Note(EqualTemperamentTuning.E_5,0.5,1),new Note(EqualTemperamentTuning.D_5,1))
  3. ;
  4.  
  5. private Note[] notes = new Note[2];
  6.  
  7. Melody (Note note1,Note note2){
  8. this.notes[0] = note1;
  9. this.notes[1] = note2;
  10. }
  11. }

然后我将在运行时加载到NotePhrase对象中.这不是很好,因为我必须为具有不同音符量的旋律创建一个新的构造函数.如果我以相反的方式进行并用一系列音符构造枚举,那么我只是在其他地方“写”旋律,这两部分看起来更令人困惑……

所以我坚持如何正确地构建它?即要创建什么类以及应该保留哪些信息…我想让这个“正确”因为,我可能希望将来扩展包含效果(回声等)的符号,我已经找到了我的非常很少的经验,正确的类,结构和关系(甚至名称)可以使我的程序非常容易或难以理解.

对于这篇文章道歉,这可能不是一个非常好的(咳咳)问题,但作为一个java& OOP初学者,非常欢迎任何提示

编辑**

谢谢你的回答&建议,非常有帮助.考虑到这个案例中给出的答案,让我重新思考我的一般音频实现,现在非常不稳定.不知道我应该把谁标记为正确,因为我真的只是将所有建议都放在船上并尝试从那里开始.

解决方法

不要为Melody使用枚举,因为Melody不代表真正的常量,而是Note数据的集合.我建议不要使用数组,而是使用ArrayList< Note>这更灵活.

在Melody中,我将Note添加到Measure和Beat中,并将Melody类赋予addNote(Note,int measure,int beatFraction),同样用于remove Note.

考虑将12个核心注释作为枚举,然后使用它们加上一个octave int来创建一个Note对象.

……有很多方法可以玩这个练习. “关键”是继续进行实验.

猜你在找的Java相关文章