2012-05-22 16 views
6

Ich möchte herausfinden, wie Noten aufgebaut wurden. Beispiel für ein Instrument (Violine oder Klavier), die Note LA4 (A4) hat die Hauptfrequenz FC bei 440 Hz mit einer spezifischen Amplitude AC, aber es muss auch andere Frequenzen (Harmonische?) FH mit anderen Amplituden AH haben.Note Synthesis, Harmonics (Violine, Klavier, Gitarre, Bass), Frequenzen, MIDI

Die Oberwellen haben andere Frequenzen, die von der Hauptfrequenz mit Amplituden (fast) weniger als die Amplitude der Hauptfrequenz abhängen.

Forming (Gebäude) Hinweise

ich wissen will, wie gebildet (hergestellt), um die Noten (Keine Zeit wird berücksichtigt).

Beispiel: A4 = AC (FC) + AH1 (FH1) + AH2 (FH2) + AH3 (FH3) + AH4 (FH4) .... AHn (FHn) Vielleicht FH1 = 2 * FC, FH2 = 3 * FC, FH3 = 4 * FC, und so weiter ....

zwischen den Instrumenten (Violine und Klavier) Der Vergleich

für Klavier, hat Hauptfrequenz FC Der Hinweis LA4 (A4) bei 440Hz, und Vielleicht, FC (Klavier) = FC (Violine), FH1 (Klavier) = FH1 (Violine), FH2 (Klavier) = FH2 (Violine), und so weiter ....

Aber, Wechselstrom (Pian o) = AC (Violine), AH1 (Klavier) = AH1 (Violine), AH2 (Klavier) = AH2 (Violine), und so weiter ....

Beispiel für meine Frage ist:! http://www.phys.unsw.edu.au/jw/sound.spectrum.html

Ich möchte diese Noten spielen vermeiden MIDI-Format, das kann in Java/C# (oder andere Programmiersprachen) implementiert werden Später, und mehr Kontrolle über meine Sounds.

Vielen Dank.

Ana

Antwort

3

ich diese haben ...

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()); 
     } 

Dieser Code wird in Violine Instrument verwendet:

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); 
    } 

diesen Code Versuchen Sie, mein Sound ist nicht perfekt, aber sehr ähnlich ist.

+0

Großartig, ist sehr ähnlich ... – Anita

+0

Dieser Code hat viele fehlende Deklarationen, ist mehrdeutige Variablennamen. kann nicht laufen. pelase deklarieren nicht deklarierte Variablen, oder entfernen Sie sie aus dem Code. undeclared varible wird im Code verwendet, ohne dass es sich um einen initialisierten Wert handelt .... im Moment ist der Code nur von inspiriert. –

0

Wenn ich richtig verstehe, Sie versuchen, eine Fourier-Synthese zu tun, in der Hoffnung, dass etwas ähnlich wie das Original Instrument führen. Ich sehe die Chancen für den Erfolg recht schlank:

  • es wird nicht funktionieren midi verwenden, da diese reine Sinuswellen zu kombinieren erfordern würde (die durch Standardinstrumente MIDI GS nicht verfügbar sind)
  • braucht man riesige Datenmenge schwer zu bekommen; beachten Sie, dass Ihre Koeffizienten nicht spezifisch für „Klavier“ allein sind aber auch variieren mit die Tonhöhe, so „piano a5“ hat verschiedene Werte von „piano a6“
    • dieses Modell den stabilen Zustand des Tons geht davon aus (a anderes Ziel ist nicht erreichbar durch Hinzufügen von Sinuswellen); die Charakteristik eines Instruments ist jedoch entschlossene durch seine Angriffsphase

Ich würde John Pierce, The Science of Musical Ton für eine Einführung empfehlen.

2

Seien Sie sich bewusst, dass das, was Sie unternehmen, eine große Aufgabe ist.Wenn es Ihr Ziel ist, einen eigenen Synthesizer zu erstellen, der wie ein Klavier, eine Geige usw. klingt, indem Obertöne mit bestimmten Amplituden addiert werden, ist es unglaublich schwierig, einen Klang zu erzeugen, der in irgendeiner Weise realistisch ist. Die Obertöne eines akustischen Instruments variieren im Laufe der Zeit in einer komplexen Art und Weise. Als Guidot-Noten werden die Attack- und Delay-Teile des Sounds sehr unterschiedlich sein. Wenn Sie versuchen, die relativen Amplituden eines realen Instruments an einer Anzahl von Punkten im Laufe der Zeit zu messen und dann die Sinuswellen zu synthetisieren, dann ist das Beste, was Sie erreichen werden, etwas, das sich wie ein Kinderspielzeug anhört.

Wenn Sie das möchten, müssen Sie das Spektrum der Klänge, die Sie emulieren möchten, im Zeitverlauf analysieren. Der einfachste Weg, den ich vorschlagen würde, ist Matlab, Octave oder Scipy. Wenn Sie Visualisierungen möchten, dann probieren Sie Sonic Visualizer oder Marsyas.

Wenn Sie jedoch eine realistische Wiedergabe erstellen möchten, haben Sie zwei Möglichkeiten. Man benutzt Wavetable synthesis, so viele billige Synthesizer (besonders solche auf PC-Soundkarten) arbeiten. Der andere ist, in Physical Modelling Synthesis zu schauen, der die Physik eines Instrumentes simuliert, um realistische Töne zu verursachen.