2012-05-22 9 views
6

노트 작성 방법을 찾고 싶습니다. 악기 (바이올린 또는 피아노)의 예 참고 LA4 (A4)는 440Hz에서 특정 진폭 AC를 갖는 주 (또는 중앙) 주파수 FC를 가지고 있지만 다른 진폭 AH가있는 다른 주파수 (고조파?) FH를 가져야합니다.참고 합성, 고조파 (바이올린, 피아노, 기타,베이스), 주파수, MIDI

고조파는 주 주파수의 진폭보다 진폭이 작은 (주) 주 주파수에 종속적 인 다른 주파수를 가지고 있습니다.

형성 (건물) 나는 (아니 시간이 고려되지 않음) 형성 (설정)하는 방법을 메모를 알고 싶어

노트.

예 : A4 = AC (FC) + AH1 (FH1) + AH2 (FH2) + 아시안 하이웨이 3 호선 (FH3) + AH4 미정 (FH4) .... 안 (FHn) , FH1 = 2 * FC, FH2 = 3 * FC, FH3 = 4 * FC 등 .... 악기 (바이올린 피아노) 피아노

사이 비교

, 노트 LA4 (A4)를 갖고 주요 주파수 FC FC (피아노) = FC (바이올린), FH1 (피아노) = FH1 (바이올린), FH2 (피아노) = FH2 (바이올린) 등 ...

그러나, AC (피안) O = AC (바이올린), AH1 (피아노) = AH1 (바이올린), AH2 (피아노) = AH2 (바이올린), 및 등등 .... 내 질문의

예는 다음과 같습니다!!! http://www.phys.unsw.edu.au/jw/sound.spectrum.html

MIDI 형식을 피하면서이 음표를 연주하고 싶습니다. 이것은 Java/C# (또는 다른 언어 프로그래밍)에서 구현할 수 있습니다.

감사합니다. 아나

답변

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

이 코드를 시도, 내 소리가 완벽하지 않지만 매우 유사하다.

+0

대단히 비슷합니다 ... – Anita

+0

이 코드에는 많은 누락 된 선언이 있으며 모호한 변수 이름입니다. 캔트 러닝. 선언되지 않은 변수를 선언하거나 코드에서 제거합니다. 선언되지 않은 변수는 값으로 인식되지 않고 코드에서 사용됩니다 .... 지금은 코드가 영감을 얻고 있습니다. –

0

만약 내가 제대로 이해하고

, 당신은 원래의 악기와 유사한 일이 발생합니다 바라고, 푸리에 합성을 위해 노력하고 있습니다. 나는 매우 슬림 성공을위한 기회를 참조하십시오 (표준 MIDI GS 악기로 사용할 수 없습니다)

  • 이 결합 에 순수 정현파를 필요로하기 때문에 그것은, 미디를 사용하여 작동하지 않습니다는
  • 하나의 거대한 필요 다가 오기 어려운 데이터의 양; (당신의 계수가 "피아노"혼자가 특정되지 않은, 주의뿐만 아니라 피치에 따라 달라, 그래서 "피아노 A5"가 "피아노 A6"
    • 이 모델은 톤의 안정 상태를 가정에서 서로 다른 값을 가진 사인파를 추가하여 다른 목표를 달성 할 수 없다. ); 악기의 특성은 그러나 더 결정 의 공격 단계

내가 소개 존 피어스, 뮤지컬 사운드의 과학을 추천 할 것입니다.

2

착수하는 작업이 거대한입니다.피치, 바이올린 등과 같이 특정한 진폭의 고조파를 추가하여 자신의 신디사이저를 만드는 것이 목표라면 어떤면에서는 현실감있는 사운드를 만드는 것이 매우 어렵습니다. 어쿠스틱 악기의 고조파는 복잡한 방식으로 시간에 따라 변합니다. guidot 메모로, 소리의 공격과 지연 부분은 매우 다를 것입니다. 시간이 지남에 따라 여러 가지 점에서 실제 악기의 상대적인 진폭을 측정하고 사인파를 합성하려고 시도하면 달성 할 수있는 최선은 어린이 장난감처럼 들릴 것입니다.

원하는대로한다면 에뮬레이션하려는 사운드의 시간에 대한 스펙트럼을 분석해야합니다. 가장 쉬운 방법은 Matlab, Octave 또는 Scipy와 같은 것을 사용하는 것입니다. 시각화를 원하면 Sonic Visualiser 또는 Marsyas를 시도하십시오.

그러나 현실적인 재생을 만들고 싶다면 두 가지 옵션이 있습니다. 하나는 Wavetable synthesis을 사용하는 것인데, 이는 많은 저렴한 합성기 (특히 PC 사운드 카드의 것)가 작동하는 방법입니다. 다른 하나는 Physical Modelling Synthesis을 들여다 보면 현실적인 사운드를 생성하는 악기의 물리학을 시뮬레이션합니다.

나는이이