How do I change the decibels of a clip

142 Views Asked by At

The problem I have is that the decibals of the audiofile only changes from the initial value of programVolume (the variable) but I have a JSlider that alters the the value of the variable;however, it does not alter the decibals of the file. What do I add/change to make sure the decibal changes based off the values set to the variable from the JSlider.

  File fileSong = new File (filePath); 
  AudioInputStream input = AudioSystem.getAudioInputStream(fileSong); 
  clip = AudioSystem.getClip(); 
  clip.open(input); 
  FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
  gainControl.setValue(programVolume);
  clip.start();

EDIT:

I have added the following code:

  File fileSong = new File (filePath); 
  AudioInputStream input = AudioSystem.getAudioInputStream(fileSong);
  clip = AudioSystem.getClip(); 
  clip.open(input); 

  FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
  float range = gainControl.getMaximum() - gainControl.getMinimum();
  float gain = (range * programVolume) + gainControl.getMinimum();
  gainControl.setValue(gain);

For my JSlider (which is in the method ChangeEvent e)

    programVolume =  (float)volume.getValue() / 100; 

I am still facing the same problem. The new values recieved from the JSlider do not change the volume. Only the initial value of programVolume alters the sound.

2

There are 2 best solutions below

3
Shahrukh Qureshi On BEST ANSWER

I figured it out! Whenever the variable was altered using the JSlider the clip had to be stopped and the point at which it was stopped was to be stored onto a variable. I chose a long and then the clip had to be restarted and when it restarts it uses the new volume the user selected and it begins at the same time it left off at giving the illusion to the user that the volume was altered while the audio-file was playing when it stopped, changed volume, and resumed. The Math.Log stuff is used to calculate/convert the decibels to the volume system we know (0%-100%) or so I think.

  File fileSong = new File (filePath);
  AudioInputStream input = AudioSystem.getAudioInputStream(fileSong); 
  clip = AudioSystem.getClip(); 
  clip.open(input); 
  clip.setMicrosecondPosition(position); 

  FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); 
  float range = (float) (Math.log(userInput) / Math.log(10) * 20); 
  gainControl.setValue(range); 
  clip.start(); 
2
Phil Freihofner On

The first suggestion from @gthanop on ShaleeQureshi's answer is quite important. Reloading a Clip is very inefficient. The entire Clip has to be reloaded before it can be restarted.

Often there are issues with Controls, as these are dependent on native code that interacts with the different systems. Controls that are implemented on one PC may not be implemented on another due to features missing on that PC.

Another issue that comes up is that the changes arising from Controls are tied to buffer boundaries. If for example the buffer is a half of a second long, it would take up to a half second for the new value to become operative.

There is no "decibel" control, per se, in an audio file. Instead, the volume arises from the dynamic range of the data values that form the signal. A quiet file may only range from -0.05 to 0.05, where a loud one might be more like -0.5 to 0.5. An audio file may have sections that are loud and others that are soft, but the entirety is still encoded directly as signal values. There is no "volume" control on a .wav file.

Since the Controls provided by Java cannot be depended upon, you might want to check out the github resource AudioCue. It is basically an enhanced Clip, with real time volume controls. The code has a permissive license and is free to use or to inspect for ideas. The basic principle is to store the data in a float[] rather than a Clip, and to play it back via a SourceDataLine while making constant reference to a volume factor that is multiplied against the signal values as they stream.