SolveItproblems

SolveITProblems is a project of QFormat.net intellectual club

SolveITProblems это проект интеллектуального клуба QFormat.net

четверг, 8 апреля 2010 г.

Java Sound API, Java и работа со звуком

Решил сделать одну простенькую программу для психологического тестирования, понадобилось запись голоса тестируемого. Около 15 минут и готовый в нете сампл записи звука в wav файл уже прочитан, понят, скомпилирован и протестирован. АПИ для работы со звуком уже в стандарте, т.е. ничего качать не надо. импортируем в проект



import javax.sound.sampled.*;

и ниже я привел код из Sun-овского примера чуть-чуть отредактированного мною, управляется все еще из командной строки но изменить это ничего не стоит.

import javax.sound.sampled.*;
import java.io.*;
import javax.sound.sampled.AudioFileFormat.Type;

public class JRecorder extends Thread    {

        private TargetDataLine        m_line;
    private AudioFileFormat.Type    m_targetType;
    private AudioInputStream    m_audioInputStream;
    private File            m_outputFile;

    public JRecorder(TargetDataLine m_line, Type m_targetType,  File m_outputFile) {
        this.m_line = m_line;
        this.m_targetType = m_targetType;
        this.m_audioInputStream = new AudioInputStream(m_line);
        this.m_outputFile = m_outputFile;
    }

    public void start()
    {
        m_line.start();

        super.start();
    }

        public void stopRecording()
    {
        m_line.stop();
        m_line.close();
    }


            public void run()
    {
            try
            {
                AudioSystem.write(
                    m_audioInputStream,
                    m_targetType,
                    m_outputFile);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
    }



                public static void main(String args[])
                {
                    File outputFile = new File("c:\\audiorec.wav");

        AudioFormat    audioFormat = new AudioFormat(
            AudioFormat.Encoding.PCM_SIGNED,
            44100.0F, 16, 2, 4, 44100.0F, false);

                DataLine.Info    info = new DataLine.Info(TargetDataLine.class, audioFormat);
        TargetDataLine    targetDataLine = null;
        try
        {
            targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
            targetDataLine.open(audioFormat);
        }
        catch (LineUnavailableException e)
        {
            System.out.println("unable to get a recording line");
            e.printStackTrace();
            System.exit(1);
        }

                AudioFileFormat.Type    targetType = AudioFileFormat.Type.WAVE;

                JRecorder j = new JRecorder(targetDataLine,targetType,outputFile);



                    System.out.println("Press ENTER to start the recording.");

        try
        {
            System.in.read();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        /* Here, the recording is actually started.
         */
        j.start();
        System.out.println("Recording...");

  
        System.out.println("Press ENTER to stop the recording.");
        try
        {
            System.in.read();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        j.stopRecording();
        System.out.println("Recording stopped.");
                }

}



Написать Аудио плеер еще легче, привожу семпл код

import javax.sound.sampled.*;
import java.io.*;

public class JPlayer {

String filename;
AudioInputStream ais;

public JPlayer(String filename) {
this.filename = filename;
this.initialize();
}

public void initialize()
{
try {
ais = AudioSystem.getAudioInputStream(new File(filename));
} catch (Exception e) {
System.out.println("Exception in initializing. "+e);
}

AudioFormat format = ais.getFormat();

SourceDataLine line = null;
DataLine.Info    info = new DataLine.Info(SourceDataLine.class,format);

try {
line = (SourceDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();

int    nBytesRead = 0;
byte[]    abData = new byte[128000];
while (nBytesRead != -1)
{
try
{
nBytesRead = ais.read(abData, 0, abData.length);
}
catch (IOException e)
{
e.printStackTrace();
}
if (nBytesRead >= 0)
{
int    nBytesWritten = line.write(abData, 0, nBytesRead);
}
}


} catch (Exception e) {
System.out.println("Exception in inintializing. getting line. "+e);
}

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



public static void main(String args[])
{
JPlayer jp = new JPlayer("C:\\audiorec.wav");
}

}

15 комментариев:

  1. большое спасибо, очень помогло!

    ОтветитьУдалить
  2. очень рад :) если будут вопросы пишите.

    ОтветитьУдалить
  3. Привет! Спасибо большое за пример! Буду разбираться. Эта прога пишет в файл исходный звук, а как можно преобразовать его, например пустить через фильтр, а потом записать?

    ОтветитьУдалить
  4. Сори за поздний ответ, сам фильтрами не занимался, но нашел в нете один интересный семпл, можете по нему сделать то что вам нужно

    http://www.java2s.com/Code/Java/Development-Class/Anexampleofplayingasoundwithanechofilter.htm

    п.с.
    Вам спасибо за комменты.

    ОтветитьУдалить
  5. Добрый день. Подскажите пожалуйста, как можно организовать осциллограмму проигрываемого звука, знаете как в Winamp? И чтобы все происходило в режиме реального времени?

    ОтветитьУдалить
  6. Добрый!
    Здесь

    http://www.coderanch.com/t/382467/java/java/audio-visualization-graphics

    есть код который делает то, что вам нужно. Хотя код там немножко страшный :) но жить можно, работать будет :) . Потом уже можете изменять функцию прорисовки и рисовать так как вы хотите и то что вы хотите.

    ОтветитьУдалить
  7. Здравствуйте! есть пара вопросиков:
    1) как пустить звук в определенный канал (левый, например)?
    2) как в режиме реального времени вывести микрофон в колонки?
    з.ы. и еще как работать с аудиовыходами?

    ОтветитьУдалить
  8. Здравствуйте. ответы на ваш первый вопрос в примере которые можете увидеть пройдя по ссылке:
    http://www.anyexample.com/programming/java/java_play_wav_sound_file.xml

    что касается режима реального времени для микрофона.. задача вроде не сложная но гугл никак не помог. Сам этого не делал, могу помочь лишь с алгоритмом:
    Можно сделать два потока в программе один который вечно считывает из микрофона (пример этого есть в самой статье) и Держит информацию порциями в каком-нибудь векторе внутри третьего класса служащего мостом между считыванием и исполнением.
    Второй поток запускается через каждые н доли секунды и исполняет очередной элемент вектора - порцию считанного микрофоном звука. Если "попадете" с интервалом второго потока то вроде должно все работать... Если сделаете так или найдете другое решение прошу поделиться...

    ОтветитьУдалить
  9. Анонимный11 июня 2011 г., 18:35

    Доброго времени суток!
    Вы не подскажете, как организовать регулированиe уровня громкости через "slider"?

    ОтветитьУдалить
  10. Можно так:

    SourceDataLine sdline;
    FloatControl control = (FloatControl) sdline.getControl(FloatControl.Type.VOLUME);
    control.setValue(значение вашего слайдера);

    перед тем как передавать значение слайдера умножьте его на коеффициент. по-моему там от 0 до 1 он принимает.

    Есть еще и такой метод, его я в нете нашел:

    // Set Volume
    FloatControl gainControl = (FloatControl)clip.getControl(FloatControl.Type.MASTER_GAIN);
    double gain = .5D; // number between 0 and 1 (loudest)
    float dB = (float)(Math.log(gain)/Math.log(10.0)*20.0);
    gainControl.setValue(dB);

    ОтветитьУдалить
  11. Спасибо большое, очень интересно и полезно!

    ОтветитьУдалить
  12. Анонимный1 июня 2015 г., 15:46

    большое спасибо за статью, но у меня еще вопрос если можно подскажите пожалуйста где можно взять исходный код кодеков G723 или подобных на java для передачи голоса через сеть, нужно для диплома, а все что попадалось либо готовые реализации либо платные

    ОтветитьУдалить
  13. Спасибо за статю, у меня вопрос. Как изменить громкость аудио файла в java? помогите пожалуйста.

    ОтветитьУдалить