How can I loop a sound without using 'clip' in java before writing it into a file

 ̄綄美尐妖づ 提交于 2020-01-05 04:54:09

问题


First of all thanks everyone for helping me with my previous questions.

In the following code I am taking two frequencies alternatively and writing them into a .wav format, to run it in my Windows Media Player, for a specific time given by the user. What I want is to understand how to loop those frequencies to run alternatively for that specified time, like the Ambulance's siren, and in my program both frequencies are getting played just once, alternatively. For example, if I am specifying the time as 10 seconds, then both the frequencies run for 5 seconds each at a stretch. But what I want is that the 1st frequency to run for a second or two seconds(as the user specifies) and then the 2nd frequency to run for that similar second and then again the 1st frequency and it should keep on going till the specified time.

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;

public class AudioWrite2New {

    public static void main(String[] args) throws IOException, InterruptedException, LineUnavailableException {

        Scanner in = new Scanner(System.in);
        final double SAMPLING_RATE = 44100;             // Audio sampling rate
        int time = in.nextInt();                        //Time specified by user in seconds
//        int time2 = in.nextByte();
        int frequency1 = in.nextInt();                   //Frequency1 specified by the user in hz
        int frequency2 = in.nextInt();                   //Frequency2 specified by the user in hz

        float buffer[] = new float[(int) (time/2 * SAMPLING_RATE)];   //Size of buffer[], which in case of 10 seconds is 441000
        float buffer1[] = new float[(int) (time/2 * SAMPLING_RATE)];   //Size of buffer1[], which in case of 10 seconds is 441000

        for (int sample = 0; sample < buffer.length; sample++) {
            double cycle = sample / SAMPLING_RATE;                  //Fraction of cycle between samples
            buffer[sample] = (float) (Math.sin(2 * Math.PI * frequency1 * cycle));
            //buffer1[sample] = (float) (Math.sin(2 * Math.PI * frequency2 * cycle));
        }
        for (int sample = 0; sample < buffer1.length; sample++) {
            double cycle = sample / SAMPLING_RATE;                  //Fraction of cycle between samples
            //buffer[sample] = (float) (Math.sin(2 * Math.PI * frequency1 * cycle));
            buffer1[sample] = (float) (Math.sin(2 * Math.PI * frequency2 * cycle));
        }
        //System.out.println(buffer[1]);
        byte byteBuffer[] = new byte[buffer.length * 2];            //Size of byteBuffer, in this case 882000
        byte byteBuffer1[] = new byte[buffer1.length * 2];            //Size of byteBuffer, in this case 882000

        int count = 0;
        for (int i = 0; i < byteBuffer.length; i++) {
            final int x = (int) (buffer[count++] * Short.MAX_VALUE);
            byteBuffer[i++] = (byte) x;
            byteBuffer[i] = (byte) (x / 256);
        }

        count = 0;
        for (int i = 0; i < byteBuffer1.length; i++) {
            final int x = (int) (buffer1[count++] * Short.MAX_VALUE);
            byteBuffer1[i++] = (byte) x;
            byteBuffer1[i] = (byte) (x / 256);
        }

        //For merging the two frequencies
        byte[] merge = new byte[byteBuffer.length + byteBuffer1.length];
        System.arraycopy(byteBuffer, 0, merge, 0, byteBuffer.length);
        System.arraycopy(byteBuffer1, 0, merge, byteBuffer.length, byteBuffer1.length);

        File out = new File("E:/RecordAudio17.wav"); //The path where user want the file data to be written

        //Construct an audio format, using 44100hz sampling rate, 16 bit samples, mono, and big 
        // endian byte ordering
        AudioFormat format = new AudioFormat((float) SAMPLING_RATE, 16, 1, true, false);

        // It uses bytebuffer as its buffer array that contains bytes that may be read from the stream.
        ByteArrayInputStream bais = new ByteArrayInputStream(merge);

        //Constructs an audio input stream that has the requested format and length in sample frames, using audio data 
        //from the specified input stream.
        AudioInputStream audioInputStream = new AudioInputStream(bais, format, buffer1.length + buffer.length);

        //Writes a stream of bytes representing an audio file of the specified file type to the external file provided.
        AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, out);

        audioInputStream.close();       //Closes this audio input stream
    }
}

And as I am quite new in Java and JavaSounds, therefore sometimes I might ask few foolish or irrelevant questions. So please bear with me as that is the only way in which I can learn. Thanks.


回答1:


I resolved it. Although there is one minor part that I need to handle. I will update it as soon as I am done with it.

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;

public class AudioWrite2New {

    public static void main(String[] args) throws IOException, InterruptedException, LineUnavailableException {

        Scanner in = new Scanner(System.in);
        final double SAMPLING_RATE = 44100;             // Audio sampling rate
        int time = in.nextInt();                        //Time specified by user in milliseconds
        int time2 = in.nextByte();
        int frequency1 = in.nextInt();                   //Frequency1 specified by the user in hz
        int frequency2 = in.nextInt();                   //Frequency2 specified by the user in hz

        float buffer[] = new float[((int) (time * SAMPLING_RATE))/1000];   //Size of buffer[], which in case of 10 seconds is 441000
        float buffer1[] = new float[((int) (time * SAMPLING_RATE))/1000];   //Size of buffer1[], which in case of 10 seconds is 441000

        //for (int a = 1; a <= time2 / 2; a++) {
        for (int sample = 0; sample < buffer.length; sample++) {
            double cycle = sample / SAMPLING_RATE;                  //Fraction of cycle between samples
            buffer[sample] = (float) (Math.sin(2 * Math.PI * frequency1 * cycle));
            //buffer1[sample] = (float) (Math.sin(2 * Math.PI * frequency2 * cycle));
        }
        for (int sample = 0; sample < buffer1.length; sample++) {
            double cycle = sample / SAMPLING_RATE;                  //Fraction of cycle between samples
            //buffer[sample] = (float) (Math.sin(2 * Math.PI * frequency1 * cycle));
            buffer1[sample] = (float) (Math.sin(2 * Math.PI * frequency2 * cycle));
        }
        //System.out.println(buffer[1]);
        byte byteBuffer[] = new byte[buffer.length * 2];            //Size of byteBuffer, in this case 882000
        byte byteBuffer1[] = new byte[buffer1.length * 2];            //Size of byteBuffer, in this case 882000

        int count = 0;
        for (int i = 0; i < byteBuffer.length; i++) {
            final int x = (int) (buffer[count++] * Short.MAX_VALUE);
            byteBuffer[i++] = (byte) x;
            byteBuffer[i] = (byte) (x / 256);
        }

        count = 0;
        for (int i = 0; i < byteBuffer1.length; i++) {
            final int x = (int) (buffer1[count++] * Short.MAX_VALUE);
            byteBuffer1[i++] = (byte) x;
            byteBuffer1[i] = (byte) (x / 256);
        }

        int iterations = (1000*time2)/(2*time);
        byte[] merge = new byte[iterations*(byteBuffer.length + byteBuffer1.length)];
        for (int i = 0; i<iterations; i++)
        {
            //arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
            //For merging the two frequencies
            System.arraycopy(byteBuffer, 0, merge, 0+i*(byteBuffer.length + byteBuffer1.length), byteBuffer.length);
            System.arraycopy(byteBuffer1, 0, merge, byteBuffer.length+i*(byteBuffer.length + byteBuffer1.length), byteBuffer1.length);
        }

        File out = new File("E:/RecordAudio17.wav"); //The path where user want the file data to be written

        //Construct an audio format, using 44100hz sampling rate, 16 bit samples, mono, and big 
        // endian byte ordering
        AudioFormat format = new AudioFormat((float) SAMPLING_RATE, 16, 1, true, false);

        // It uses bytebuffer as its buffer array that contains bytes that may be read from the stream.
        ByteArrayInputStream bais = new ByteArrayInputStream(merge);

        //Constructs an audio input stream that has the requested format and length in sample frames, using audio data 
        //from the specified input stream.
        AudioInputStream audioInputStream = new AudioInputStream(bais, format, (buffer1.length + buffer.length) * (time2/4));

        //Writes a stream of bytes representing an audio file of the specified file type to the external file provided.
        AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, out);

        //}
        //audioInputStream.close();       //Closes this audio input stream
    }
}


来源:https://stackoverflow.com/questions/40838808/how-can-i-loop-a-sound-without-using-clip-in-java-before-writing-it-into-a-fil

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!