
org.jitsi.impl.neomedia.audiolevel.AudioLevelEffect Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of libjitsi Show documentation
Show all versions of libjitsi Show documentation
libjitsi is an advanced Java media library for secure real-time audio/video
communication
The newest version!
/*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.impl.neomedia.audiolevel;
import javax.media.*;
import javax.media.format.*;
import org.jitsi.impl.neomedia.control.*;
import org.jitsi.service.neomedia.event.*;
/**
* An effect that would pass data to the AudioLevelEventDispatcher
* so that it would calculate levels and dispatch changes to interested parties.
*
* @author Damian Minkov
* @author Emil Ivov
* @author Lyubomir Marinov
*/
public class AudioLevelEffect
extends ControlsAdapter
implements Effect
{
/**
* The indicator which determines whether AudioLevelEffect
* instances are to perform the copying of the data from input
* Buffers to output Buffers themselves (e.g. using
* {@link System#arraycopy(Object, int, Object, int, int)}).
*/
private static final boolean COPY_DATA_FROM_INPUT_TO_OUTPUT = true;
/**
* The SimpleAudioLevelListener which this instance associates with
* its {@link #eventDispatcher}.
*/
private SimpleAudioLevelListener audioLevelListener = null;
/**
* The dispatcher of the events which handles the calculation and the event
* firing in different thread in order to now slow down the JMF codec chain.
*/
private final AudioLevelEventDispatcher eventDispatcher
= new AudioLevelEventDispatcher("AudioLevelEffect Dispatcher");
/**
* The indicator which determines whether {@link #open()} has been called on
* this instance without an intervening {@link #close()}.
*/
private boolean open = false;
/**
* The supported audio formats by this effect.
*/
private Format[] supportedAudioFormats;
/**
* The minimum and maximum values of the scale
*/
public AudioLevelEffect()
{
supportedAudioFormats
= new Format[]
{
new AudioFormat(
AudioFormat.LINEAR,
Format.NOT_SPECIFIED,
16,
1,
AudioFormat.LITTLE_ENDIAN,
AudioFormat.SIGNED,
16,
Format.NOT_SPECIFIED,
Format.byteArray)
};
}
/**
* Sets (or unsets if listener is null), the listener that
* is going to be notified of audio level changes detected by this effect.
* Given the semantics of the {@link AudioLevelEventDispatcher} this effect
* would do no real work if no listener is set or if it is set to
* null.
*
* @param listener the SimpleAudioLevelListener that we'd like to
* receive level changes or null if we'd like level measurements
* to stop.
*/
public void setAudioLevelListener(SimpleAudioLevelListener listener)
{
synchronized (eventDispatcher)
{
audioLevelListener = listener;
if (open)
eventDispatcher.setAudioLevelListener(audioLevelListener);
}
}
/**
* Returns the audio level listener.
*
* @return the audio level listener or null if it does not exist.
*/
public SimpleAudioLevelListener getAudioLevelListener()
{
synchronized (eventDispatcher)
{
return audioLevelListener;
}
}
/**
* Lists all of the input formats that this codec accepts.
*
* @return An array that contains the supported input Formats.
*/
public Format[] getSupportedInputFormats()
{
return supportedAudioFormats;
}
/**
* Lists the output formats that this codec can generate.
*
* @param input The Format of the data to be used as input to the
* plug-in.
* @return An array that contains the supported output Formats.
*/
public Format[] getSupportedOutputFormats(Format input)
{
return
new Format[]
{
new AudioFormat(
AudioFormat.LINEAR,
((AudioFormat)input).getSampleRate(),
16,
1,
AudioFormat.LITTLE_ENDIAN,
AudioFormat.SIGNED,
16,
Format.NOT_SPECIFIED,
Format.byteArray)
};
}
/**
* Sets the format of the data to be input to this codec.
*
* @param format The Format to be set.
* @return The Format that was set.
*/
public Format setInputFormat(Format format)
{
return (format instanceof AudioFormat) ? (AudioFormat) format : null;
}
/**
* Sets the format for the data this codec outputs.
*
* @param format The Format to be set.
* @return The Format that was set.
*/
public Format setOutputFormat(Format format)
{
return (format instanceof AudioFormat) ? (AudioFormat) format : null;
}
/**
* Performs the media processing defined by this codec.
*
* @param inputBuffer The Buffer that contains the media data to be
* processed.
* @param outputBuffer The Buffer in which to store the processed
* media data.
* @return BUFFER_PROCESSED_OK if the processing is successful.
* @see PlugIn
*/
public int process(Buffer inputBuffer, Buffer outputBuffer)
{
/*
* In accord with what an Effect is generally supposed to do, copy the
* data from the inputBuffer into outputBuffer.
*/
if (COPY_DATA_FROM_INPUT_TO_OUTPUT)
{
// Copy the actual data from the input to the output.
Object data = outputBuffer.getData();
int inputBufferLength = inputBuffer.getLength();
byte[] bufferData;
if ((data instanceof byte[]) &&
(((byte[])data).length >= inputBufferLength))
{
bufferData = (byte[])data;
}
else
{
bufferData = new byte[inputBufferLength];
outputBuffer.setData(bufferData);
}
outputBuffer.setLength(inputBufferLength);
outputBuffer.setOffset(0);
System.arraycopy(
inputBuffer.getData(), inputBuffer.getOffset(),
bufferData, 0,
inputBufferLength);
// Now copy the remaining attributes.
outputBuffer.setFormat(inputBuffer.getFormat());
outputBuffer.setHeader(inputBuffer.getHeader());
outputBuffer.setSequenceNumber(inputBuffer.getSequenceNumber());
outputBuffer.setTimeStamp(inputBuffer.getTimeStamp());
outputBuffer.setRtpTimeStamp(inputBuffer.getRtpTimeStamp());
outputBuffer.setFlags(inputBuffer.getFlags());
outputBuffer.setDiscard(inputBuffer.isDiscard());
outputBuffer.setEOM(inputBuffer.isEOM());
outputBuffer.setDuration(inputBuffer.getDuration());
}
else
{
outputBuffer.copy(inputBuffer);
}
/*
* At long last, do the job which this AudioLevelEffect exists for i.e.
* deliver the data to eventDispatcher so that its audio level gets
* calculated and delivered to audioEventListener.
*/
eventDispatcher.addData(outputBuffer);
return BUFFER_PROCESSED_OK;
}
/**
* Gets the name of this plug-in as a human-readable string.
*
* @return A String that contains the descriptive name of the
* plug-in.
*/
public String getName()
{
return "Audio Level Effect";
}
/**
* Opens this effect.
*
* @throws ResourceUnavailableException If all of the required resources
* cannot be acquired.
*/
public void open()
throws ResourceUnavailableException
{
synchronized (eventDispatcher)
{
if (!open)
{
open = true;
eventDispatcher.setAudioLevelListener(audioLevelListener);
}
}
}
/**
* Closes this effect.
*/
public void close()
{
synchronized (eventDispatcher)
{
if (open)
{
open = false;
eventDispatcher.setAudioLevelListener(null);
}
}
}
/**
* Resets its state.
*/
public void reset()
{
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy