Вопрос по audio – Синтез нот, гармоники (скрипка, фортепиано, гитара, бас), частоты, MIDI [закрыто]

7

Я хочу узнать, как создавались заметки. Пример для инструмента (скрипка или фортепиано), нота LA4 (A4) имеет основную (или центральную) частоту FC на частоте 440 Гц с определенной амплитудой переменного тока, но также должна иметь другие частоты (гармоники?) FH с другими амплитудами AH.

Гармоники имеют другие частоты, которые зависят от основной частоты с амплитудами (почти) меньше, чем амплитуда основной частоты.

Forming (building) Notes

Я хочу знать, как формируется (устанавливается) заметки (время не рассматривается).

Пример: A4 = AC (FC) + AH1 (FH1) + AH2 (FH2) + AH3 (FH3) + AH4 (FH4) .... AHn (FHn) Может быть, FH1 = 2 * FC, FH2 = 3 * FC, FH3 = 4 * FC и так далее ....

Comparing between instruments (Violin and Piano)

Для фортепиано Note LA4 (A4) имеет основную частоту FC на частоте 440 Гц, и Может быть, 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 # (или другом языке программирования), и больше контроля над моими звуками.

Спасибо.

изречений

Ваш Ответ

3   ответа
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);
  }

Попробуйте этот код, мой звук не идеален, но очень похож.

Отлично, очень похоже ... Anita
в этом коде много пропущенных объявлений, это неоднозначные имена переменных. не могу бежать. pelase объявляет необъявленные переменные или удаляет их из кода. необъявленная переменная используется в коде, не будучи инициализированным значением .... прямо сейчас, код должен только вдохновляться.
0

вы пытаетесь сделать синтез Фурье, надеясь, что получится что-то похожее на оригинальный инструмент. Я вижу шансы на успех довольно невелики

it won't work using midi, since this would require pure sine waves to combine (which are not available by standard MIDI GS instruments) one needs huge amount of data difficult to come by; note, that your coefficients are not specific to "piano" alone but also vary with the pitch, so "piano a5" has different values from "piano a6" this model assumes the stable state of the tone (a different goal is not achievable by adding sine waves); the characteristic of an instrument is however more determined by its attack phase

Я бы порекомендовал Джон Пирс, «Наука музыкального звука» для вступления.

2

huge задача. Если ваша цель - создать собственный синтезатор, который может звучать как пианино, скрипка и т. Д. Путем добавления гармоник с определенными амплитудами, то невероятно сложно создать реалистичный звук. Гармоники акустического инструмента меняются со временем сложным образом. Как отмечает Гвидо, части звука атаки и задержки будут сильно отличаться. Если вы попытаетесь измерить относительные амплитуды реального инструмента в нескольких точках во времени и затем синтезировать синусоиды, то лучшее, чего вы добьетесь, - это то, что будет звучать как детская игрушка.

Если это то, что вы хотите сделать, вам нужно будет проанализировать спектр звуков, которые вы хотите эмулировать, с течением времени. Самый простой способ, который я бы предложил, это использовать что-то вроде Matlab, Octave или Scipy. Если вы хотите визуализации, попробуйте Sonic Visualiser или Marsyas.

Однако, если вы хотите создать реалистичное воспроизведение, у вас есть два варианта. Одним из них является использованиеWavetable синтез, это то, сколько дешевых синтезаторов (особенно те, на звуковых картах ПК) работают. Другой, чтобы посмотреть вСинтез физического моделирования который имитирует физику инструмента для создания реалистичных звуков.

Похожие вопросы