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. Доброго времени суток!
    Вы не подскажете, как организовать регулировани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. большое спасибо за статью, но у меня еще вопрос если можно подскажите пожалуйста где можно взять исходный код кодеков G723 или подобных на java для передачи голоса через сеть, нужно для диплома, а все что попадалось либо готовые реализации либо платные

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

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