【问题标题】:Note Synthesis, Harmonics (Violin, Piano, Guitar, Bass), Frequencies, MIDI [closed]音符合成、谐波(小提琴、钢琴、吉他、贝斯)、频率、MIDI [关闭]
【发布时间】:2012-05-28 23:56:52
【问题描述】:

我想知道,笔记是如何构建的。 以乐器(小提琴或钢琴)为例,Note LA4 (A4) 具有 440Hz 的主(或中心)频率 FC,具有特定幅度 AC,但它还必须具有其他频率(谐波?) FH,具有其他幅度 AH。

谐波还有其他频率取决于主频率,其幅度(几乎)小于主频率的幅度。

形成(建造)笔记

我想知道笔记是如何形成(建立)的(不考虑时间)。

示例: A4 = AC(FC) + AH1(FH1)+ AH2(FH2) + AH3(FH3) + AH4(FH4)....AHn(FHn) 也许,FH1 = 2*FC,FH2 = 3*FC,FH3 = 4*FC,等等......

乐器之间的比较(小提琴和钢琴)

对于钢琴,Note LA4 (A4) 的主频率 FC 为 440Hz,并且 也许,FC(钢琴)= FC(小提琴),FH1(钢琴)= FH1(小提琴),FH2(钢琴)= FH2(小提琴),等等......

但是,AC(钢琴)!= AC(小提琴),AH1(钢琴)!= AH1(小提琴),AH2(钢琴)!= AH2(小提琴),等等......

我的问题示例是: http://www.phys.unsw.edu.au/jw/sound.spectrum.html

我想弹奏这个音符避免使用 MIDI 格式,这可以在 Java/C#(或其他语言编程)中实现,然后更多地控制我的声音。

谢谢。

安娜

【问题讨论】:

    标签: audio instruments time-frequency


    【解决方案1】:

    如果我理解正确,您正在尝试进行傅立叶合成,希望得到与原始仪器相似的结果。我认为成功的机会非常渺茫:

    • 它不能使用 midi,因为这需要纯正弦波 组合(标准 MIDI GS 乐器不可用)
    • 需要海量数据来之不易;笔记, 您的系数不仅特定于“钢琴”,而且还随 音高,所以“piano a5”与“piano a6”有不同的值
      • 此模型假定音调处于稳定状态(无法实现不同的目标 通过添加正弦波);然而,乐器的特性更加确定 按其攻击阶段

    我会推荐 John Pierce,音乐声音的科学作为介绍。

    【讨论】:

      【解决方案2】:

      请注意,您正在执行的是一项巨大任务。如果您的目标是创建自己的合成器,通过将具有特定幅度的谐波相加来听起来像钢琴、小提琴等,那么创建一个以任何方式逼真的声音都是非常困难的。声学乐器的谐波以复杂的方式随时间变化。正如 guidot 所指出的,声音的起音和延迟部分会有很大的不同。如果您尝试随着时间的推移在多个点上测量真实乐器的相对幅度,然后合成正弦曲线,那么您将获得的最佳效果就是听起来像孩子的玩具。

      如果这是您想要做的,那么您将需要分析您想要模拟的声音随时间变化的频谱。我建议的最简单的方法是使用 Matlab、Octave 或 Scipy 之类的东西。如果您想要可视化效果,请尝试使用 Sonic Visualiser 或 Marsyas。

      但是,如果您想创建逼真的回放,那么您有两个选择。一种是使用Wavetable synthesis,这是有多少便宜的合成器(尤其是PC声卡上的合成器)可以工作的。另一种是查看Physical Modelling Synthesis,它模拟了乐器的物理特性以创建逼真的声音。

      【讨论】:

        【解决方案3】:

        我有这个……

            int iTone = 40;   //Tone to be interpreted
            iSmplRate = 32000;  //Sample Rate
            int NumBytesPerSample = 16;  // 8 or 16
            int NumChannels = 2;  //1 Mono, 2 Stereo
            double Duration = 6.5; //Seconds performing
            Short sAmplit = 1200;
            int iNumSmpl = (int)(SampleRate*Duration);
            NumTotalBytes = (int)(SampleRate*Duration*NumBytesPerSample*NumChannels);
            ByteBuffer bbWav = ByteBuffer.allocate(NumTotalBytes);
        
        
            double dMaxInstr = (double)Short.MIN_VALUE;
            double dMinInstr = (double)Short.MAX_VALUE;
        
        
            //Amplitude for violin's armonics 
            double[] violAmps = {1.0, 0.286699025, 0.150079537, 0.042909002, 
                                0.203797365, 0.229228698, 0.156931925, 
                                0.115470898, 0.0, 0.097401803, 0.087653465, 
                                0.052331036, 0.052922462, 0.038850593, 
                                0.053554676, 0.053697434, 0.022270261, 
                                0.013072562, 0.008585879, 0.005771505,
                                0.004343925, 0.002141371, 0.005343231, 
                                0.000530244, 0.004711017, 0.009014153};
        
            //Amplitude for piano's armonics 
            double[] pianAmps = {1.0, 0.399064778, 0.229404484, 0.151836061,
                                0.196754229, 0.093742264, 0.060871957,
                                0.138605419, 0.010535002, 0.071021868,
                                0.029954614, 0.051299684, 0.055948288,
                                0.066208224, 0.010067391, 0.00753679,
                                0.008196947, 0.012955577, 0.007316738,
                                0.006216476, 0.005116215, 0.006243983,
                                0.002860679, 0.002558108, 0.0, 0.001650392};
            double[] operator = {1.0};
            if (instrument.equals("violin")) {
              operator = violAmps;
            }
            if (instrument.equals("piano")) {
              operator = pianAmps;
            }
            double dFreq = 440.0*Math.pow(2.0, (iTone-69)/12.0;
        
            double dFreqRel = iSmplRate/dFreq;
            Integer iSampleInstrument = null;
            double PI2 = 2*Math.PI;
        
            int[] iSamplesInstr = new int[iNumSmpl];
            for (int i = 0;i < iNumSmpl; i++) {
              Double Angle = i*PI2/dFreqRel;
              Double dInstrument = 0.0;
              for (int a = 1; a <=operator.length; a++) {
                dInstrument += operator[a-1]*Math.sin((double)a*Angle);
              }
        
              dMaxInstr = (dInstrument>dMaxInstr)?dInstrument:dMaxInstr;
              dMinInstr = (dInstrument<dMinInstr)?dInstrument:dMinInstr;
        
              iSampleInstrument = (int)(sAmplit*dInstrument);
        
              if (instrument.equals("violin")) {
                double FreqEnvV = iSmplRate/6.0;
                double FracEnvV = 35.0;
                double dEnvViolin = sAmplit*DStepperExt(Math.sin(1.0*i*PI2/FreqEnvV),4)/FracEnvV;
                iSampleInstrument = (int)(iSampleInstrument+dEnvViolin);
              }
              if (instrument.equals("piano")) {
                double FracEnvP = 8.0/10.0;
                double AngP = (double)i/(iSmplRate*FracEnvP);
                double EnvPiano = 1.0/Math.exp(AngP);
                iSampleInstrument = (int)(iSampleInstrument*EnvPiano);
              }
              dMxSmplInstr = (iSampleInstrument>dMxSmplInstr)?iSampleInstrument:dMxSmplInstr;
              dMnSmplInstr = (iSampleInstrument<dMnSmplInstr)?iSampleInstrument:dMnSmplInstr;
              iSamplesInstr[i] = iSampleInstrument;
            }
        
            double dMaxAbs = 
                    (Math.abs(dMaxInstr)>Math.abs(dMinInstr))?Math.abs(dMaxInstr):Math.abs(dMinInstr);
            double dMxAbsSmpl = 
                    (Math.abs(dMxSmplInstr)>Math.abs(dMnSmplInstr))?Math.abs(dMxSmplInstr):Math.abs(dMnSmplInstr);
            double dNormal = 1.0;
            if (dMxAbsSmpl > 32768.0) {
              dNormal = 32768.0/dMxAbsSmpl;
            }
        
            for (int i = 0;i < iNumSmpl; i++) {
              short sSampleInst = (short)(iSamplesInstr[i]*dNormal);
              try {
                if (iNumByteSmpl == 2) {
                  bbWav.put((byte)((sSampleInst >> 0) & 0xFF));
                  bbWav.put((byte)((sSampleInst >> 8) & 0xFF));
                  if (iNumChnnls == 2) {
                    bbWav.put((byte)((sSampleInst >> 0) & 0xFF));
                    bbWav.put((byte)((sSampleInst >> 8) & 0xFF));
                  }
                } else {
                  byte ByteSample = (byte)((sSampleInst >> 8) & 0xFF);
                  short ShrtSample = (short)(ByteSample & 0xFF);
                  ShrtSample += 128;
                  bbWav.put((byte)(ShrtSample & 0xFF));
                  if (iNumChnnls == 2) {
                    bbWav.put((byte)(ShrtSample & 0xFF));
                  }
                }
              } catch (Exception e) {
                System.out.println(e.getMessage());
              }
        

        此代码用于小提琴乐器:

          private Double DStepperExt(Double Val, Integer Steps) {
            //Return a value inside in range defined by step
            //Divide [-1.0,1.0]/(Steps-1), retorning the value according to the range
            //The value must be between 0.0 and 1.0
            if (Steps <= 0.0) { 
              return 0.0;
            }
            if (Val != -1.0 && Val != 1.0) {
              Val = Val - Val.intValue();
            }
            Double sDouble = new Double(Steps-1);
            Double bdStep = 2.0/sDouble;
            Double bdRef = bdStep/2.0;
            bdRef = bdRef - 1.0;
            Double bdInit = -1.0;
        
            Double bdRet = null;
            for (int c = 0; c<=sDouble;c++) {
              if (Val < bdRef) {
                bdRet = bdInit;
                break;
              } else {
                bdInit = bdInit+bdStep;
                bdRef = bdRef+bdStep;
              }
            }
            return Math.min(bdRet.doubleValue(),1.0);
          }
        

        试试这段代码,我的声音并不完美,但非常相似。

        【讨论】:

        • 很好,很相似...
        • 这段代码有很多缺失的声明,是模棱两可的变量名。不能跑。请声明未声明的变量,或从代码中删除它们。未声明的变量在代码中使用而没有初始化值....现在,代码仅受 .
        猜你喜欢
        • 2011-10-20
        • 1970-01-01
        • 2011-09-23
        • 2014-08-28
        • 2011-05-12
        • 1970-01-01
        • 2010-12-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多