2011-12-25 2 views
7

Java의 모든 주파수에서 사인파 사운드를 생성하는 가장 간단한 방법은 무엇입니까? 샘플 크기가 2 바이트 이상이면 도움이되지만 실제로는 중요하지 않습니다.Java의 사인파 사운드 생성기

감사

답변

9

독립된 예는 Beeper을 참조하십시오.


아마도 단순한 뭔가?

조각의 51 개 라인 (아래 반복 - 한 줄 & 인라인 의견을 밖으로 간격) 그 링크 대답의 상단에 표시 같은 톤을 생성만큼이나 간단하다 OK, 당신이 할 수있는 (도착 고조파에 대해 5 개 이상의 라인을 추출).

사람들은 순수한 톤을 생성하기 위해 툴킷에 내장 된 방법이라고 가정하는 것처럼 보입니다. 그것은 아니며, 하나를 만들기 위해 약간의 계산이 필요합니다. 당신은 당신이 시작하는 몇 가지 쉬운 코드를 원하는 경우

/** Generates a tone, and assigns it to the Clip. */ 
public void generateTone() 
    throws LineUnavailableException { 
    if (clip!=null) { 
     clip.stop(); 
     clip.close(); 
    } else { 
     clip = AudioSystem.getClip(); 
    } 
    boolean addHarmonic = harmonic.isSelected(); 

    int intSR = ((Integer)sampleRate.getSelectedItem()).intValue(); 
    int intFPW = framesPerWavelength.getValue(); 

    float sampleRate = (float)intSR; 

    // oddly, the sound does not loop well for less than 
    // around 5 or so, wavelengths 
    int wavelengths = 20; 
    byte[] buf = new byte[2*intFPW*wavelengths]; 
    AudioFormat af = new AudioFormat(
     sampleRate, 
     8, // sample size in bits 
     2, // channels 
     true, // signed 
     false // bigendian 
     ); 

    int maxVol = 127; 
    for(int i=0; i<intFPW*wavelengths; i++){ 
     double angle = ((float)(i*2)/((float)intFPW))*(Math.PI); 
     buf[i*2]=getByteValue(angle); 
     if(addHarmonic) { 
      buf[(i*2)+1]=getByteValue(2*angle); 
     } else { 
      buf[(i*2)+1] = buf[i*2]; 
     } 
    } 

    try { 
     byte[] b = buf; 
     AudioInputStream ais = new AudioInputStream(
      new ByteArrayInputStream(b), 
      af, 
      buf.length/2); 

     clip.open(ais); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 
+1

['Note'] (http://stackoverflow.com/a/2065693/230513)도 참조하십시오. – trashgod

7

는 실제 웨이브 수준을 만들 수 Java Sound APIMath.sin를 사용합니다.

http://www.developer.com/java/other/article.php/2226701에는 제가 전에 언급 한 훌륭한 튜토리얼이 있습니다. http://jsresources.org/examples/이 또 다른 유용한 참고 자료였습니다.

+0

일부 샘플 코드가 도움이 될 스트리밍,하지만 난 developer.com 기사 샘플 코드로 가득하다 – milo

+0

을 통해이 찾고 노력하겠습니다. – ziesemer

6

,이 도움이

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.SourceDataLine; 

public class SinSynth { 
    // 
    protected static final int SAMPLE_RATE = 16 * 1024; 


    public static byte[] createSinWaveBuffer(double freq, int ms) { 
     int samples = (int)((ms * SAMPLE_RATE)/1000); 
     byte[] output = new byte[samples]; 
      // 
     double period = (double)SAMPLE_RATE/freq; 
     for (int i = 0; i < output.length; i++) { 
      double angle = 2.0 * Math.PI * i/period; 
      output[i] = (byte)(Math.sin(angle) * 127f); } 

     return output; 
    } 



    public static void main(String[] args) throws LineUnavailableException { 
     final AudioFormat af = new AudioFormat(SAMPLE_RATE, 8, 1, true, true); 
     SourceDataLine line = AudioSystem.getSourceDataLine(af); 
     line.open(af, SAMPLE_RATE); 
     line.start(); 

     boolean forwardNotBack = true; 

     for(double freq = 400; freq <= 800;) { 
      byte [] toneBuffer = createSinWaveBuffer(freq, 50); 
      int count = line.write(toneBuffer, 0, toneBuffer.length); 

      if(forwardNotBack) { 
       freq += 20; 
       forwardNotBack = false; } 
      else { 
       freq -= 10; 
       forwardNotBack = true; 
     } } 

     line.drain(); 
     line.close(); 
    } 

} 
+0

이것은 읽기가 쉽지만 마법 번호 127f는 어디에서 왔습니까? – nont

+1

@nont sin은 -1.0에서 1.0으로 값을 반환하고, 127을 곱하면 1 바이트의 전체 크기 (-127에서 +127)의 사인파를 제공합니다 (바이트로 캐스트 됨) –

0

첫 번째 I 조언에이 노트의 frequences를 반환하고, 바이트 배열로 변환 클래스 을 만들 수 있습니다.

그런 다음 매우 easly

protected static final int SAMPLE_RATE = 8 * 1024; 


    public static void main(String[] args) throws LineUnavailableException { 
     final AudioFormat af = new AudioFormat(SAMPLE_RATE, 8, 1, true, true); 
     SourceDataLine line = AudioSystem.getSourceDataLine(af); 
     line.open(af, SAMPLE_RATE); 
     line.start(); 

     // fist argument is duration of playing note 
     byte[] noteDo = Note.DO.getTone(1, SAMPLE_RATE); 
     byte[] noteRe = Note.RE.getTone(0.5, SAMPLE_RATE); 
     byte[] noteMi = Note.MI.getTone(1.5, SAMPLE_RATE); 

     line.write(noteDo, 0, noteDo.length); 
     line.write(noteRe, 0, noteRe.length); 
     line.write(noteMi, 0, noteMi.length); 

     line.drain(); 
     line.close(); 
    } 



public enum Note { 

    DO(0.0f), DO_DIEZ(1.0f), 
    RE(2.0f), RE_DIEZ(3.0f), 
    MI(4.0f), 
    FA(5.0f), FA_DIEZ(6.0f), 
    SOL(7.0f),SOL_DIEZ(8.0f), 
    LYA(9.0f),LYA_DIEZ(10.0f), 
    SI(11.0f); 


    private final double mPhase; 

    Note(double phase) { 
     mPhase = phase; 
    } 

    public double getNoteFrequencies() { 

     double index = getmPhase()/ 12.0d; 

     return 440 * Math.pow(2, index); 
    } 

    public static Note getNote(double phase) throws Exception { 

     Note findNote = null; 

     for (Note note : Note.values()){ 
      if (note.getmPhase() == phase){ 
       findNote = note; 
      } 
     } 

     if (findNote == null) 
      throw new Exception("Note not found: Ilegal phase " + phase); 
     else 
      return findNote; 
    } 

    public byte[] getTone(double duration, int rate){ 

     double frequencies = getNoteFrequencies(); 

     int maxLength = (int)(duration * rate); 
     byte generatedTone[] = new byte[2 * maxLength]; 

     double[] sample = new double[maxLength]; 
     int idx = 0; 

     for (int x = 0; x < maxLength; x++){ 
      sample[x] = sine(x, frequencies/rate); 
     } 


     for (final double dVal : sample) { 

      final short val = (short) ((dVal * 100f)); 

      // in 16 bit wav PCM, first byte is the low order byte 
      generatedTone[idx++] = (byte) (val & 0x00ff); 
      generatedTone[idx++] = (byte) ((val & 0xff00) >>> 8); 

     } 

     return generatedTone; 
    } 

    private double sine(int x, double frequencies){ 
     return Math.sin( 2*Math.PI * x * frequencies); 
    } 

    public double getmPhase() { 
     return mPhase; 
    } 
}