Sine Wave Sound Generator in Java

后端 未结 7 1975
时光说笑
时光说笑 2020-12-05 01:22

What\'s the simplest way to generate a sine wave sound at any frequency in Java? A sample size more than 2 bytes would help, but it doesn\'t really matter.

7条回答
  •  庸人自扰
    2020-12-05 01:53

    In a first I advice create class Note, which return frequences of note, and convert it to byte array.

    Then stream it very 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;
        }
    }
    

提交回复
热议问题