2014-10-28 2 views
1

targetDataLine에 의해 생성 된 바이트 배열을 조작하여 오디오 내용의 볼륨을 변경할 수 있습니까? 나는 자바로 운영체제 볼륨 레벨을 바꿀 수 없다는 것을 안다. 그래서 신호 자체를 조작하여 볼륨을 변경할 수 있는지 스스로에게 묻고 있습니다. 가능한가? 그렇다면 어떻게? 당신이 샘플이있는 경우, 게인을 변경하면 간단Java에서 targetDataLine에 의해 생성 된 바이트 스트림을 조작하여 사운드 볼륨을 변경할 수 있습니까?

+0

생각해보십시오 * 전적으로 오디오 스트림의 형식에 따라 달라집니다. 그 스펙을 알고 스트림의 적절한 바이트를 수정해야합니다. 매우 익숙하지 않은 Im이지만 일부 오디오 포맷에는 헤더가 있고 다른 것들은 없다는 것을 알고 있습니다. 가능한 경우에만 거기에서 수정해야 할 수도 있고 롤업 할 때 각 바이트 시퀀스를 수정해야 할 수도 있습니다. 결과적으로 클리핑이 발생하고 오디오 품질이 저하 될 수 있음을 알고 있습니다. . –

답변

1

, 단지 모든 샘플을 곱하면 8 비트 PCM 서명이 일이없는 한

samples[i] = samples[i] * 0.5f; // reduce by -6dB (half) 

직접 바이트를 곱하면,하지 않는 것이 좋습니다. 직접 바이트 스트림을 디코딩하는 방법을 배우려면 내 Q & A 'How do I use audio sample data from Java Sound'이 표시 될 수 있습니다.

지금 이론적으로 이는 Control으로도 수행 할 수 있으며 Line#getControl; 그러나, 나는 TargetDataLine이 이것을 지원하지 않는다는 것을 발견했다. 나는 SourceDataLine이 MASTER_GAIN을 지원하는 것을 발견했다. 그래서 녹음을 재생하고 있다면 출력을 사용할 수있다.

다음은 JSlider를 사용하여이를 보여주는 MCVE입니다. 중요

Gain Control

:이 예제를 실행하면, 라이브 녹음의 재생을 수행하기 때문에 헤드폰을 사용해야합니다. 스피커를 사용하는 경우 피드백을 보내드립니다. 안전을 위해 슬라이더의 기본값은 0입니다.

import javax.swing.SwingUtilities; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import java.awt.BorderLayout; 
import javax.swing.event.ChangeListener; 
import javax.swing.event.ChangeEvent; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.TargetDataLine; 
import javax.sound.sampled.SourceDataLine; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.FloatControl; 

public class LineGain { 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new JFrame("Gain"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

       JPanel content = new JPanel(new BorderLayout()); 

       JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 0); 
       content.add(slider, BorderLayout.CENTER); 

       Recorder rec = null; 
       try { 
        rec = new Recorder(); 
        rec.setGain(slider.getValue()); 
       } catch(Exception e) { 
        panic(e); 
       } 
       slider.addChangeListener(new Listener(rec)); 

       frame.setContentPane(content); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       new Thread(rec).start(); 
      } 
     }); 
    } 

    static class Listener implements ChangeListener { 
     Recorder rec; 

     Listener(Recorder rec) { 
      this.rec = rec; 
     } 

     @Override 
     public void stateChanged(ChangeEvent ce) { 
      JSlider source = (JSlider)ce.getSource(); 
      Integer newValue = source.getValue(); 
      rec.setGain(newValue); 
     } 
    } 

    static class Recorder implements Runnable { 
     final Object memSync = new Object(); 
     final AudioFormat fmt = new AudioFormat(44100f, 16, 1, true, false); 
     final int bufferSize = 2048; 

     final TargetDataLine in; 
     final SourceDataLine out; 
     final FloatControl ctrl; 

     Recorder() throws Exception { 
      in = AudioSystem.getTargetDataLine(fmt); 
      out = AudioSystem.getSourceDataLine(fmt); 
      ctrl = (FloatControl)out.getControl(FloatControl.Type.MASTER_GAIN); 

      in.open(fmt, bufferSize); 
      out.open(fmt, bufferSize); 
     } 

     void setGain(int percent) { 
      synchronized(memSync) { 
       float volume = percent/100f; 
       float range = Math.abs(ctrl.getMaximum() - ctrl.getMinimum()); 
       float value = ctrl.getMinimum() + (volume * range); 
       ctrl.setValue(value); 
      } 
     } 

     @Override 
     public void run() { 
      try { 
       byte[] buf = new byte[bufferSize]; 

       in.start(); 
       out.start(); 

       for(int b; (b = in.read(buf, 0, buf.length)) > -1;) { 
        synchronized(memSync) {} 
        out.write(buf, 0, b); 
       } 
      } catch(Exception e) { 
       panic(e); 
      } 

      in.close(); 
      out.close(); 
     } 
    } 

    static void panic(Exception e) { 
     e.printStackTrace(System.err); 
     System.exit(1); 
    } 
} 
관련 문제