Code Monkey home page Code Monkey logo

quifft's Introduction

QuiFFT logo

QuiFFT

QuiFFT is a Fourier transform (FFT) library for digital audio files. QuiFFT abstracts away the technical details of digital audio representation and wave mathematics, providing a delightfully simple interface for computing Fourier transforms in Java.

For those not experienced in signal processing, implementing a program that performs an FFT on audio data can be daunting. In addition to the interpretation of raw FFT output, it requires knowledge about discrete time sampling, signal windowing, smoothing, and overlap. QuiFFT provides the opportunity to analyze signal frequencies without the prerequisite of obtaining intimate knowledge of signal processing concepts.

Your first FFT can be as easy as one line of code:

FFTResult fft = new QuiFFT("audio.mp3").fullFFT();

This code computes an FFT for a file called audio.mp3 using QuiFFT's default FFT parameters.

Computing a more customized FFT is easy! Just add a few configuration methods to the QuiFFT object:

FFTResult fft = new QuiFFT("audio.mp3").windowSize(2048)
    .windowFunction(WindowFunction.BLACKMAN).windowOverlap(0.75).fullFFT();

Exhaustive documentation for QuiFFT can be found below.

For examples of QuiFFT in action, see the quifft-examples repo.


Table of Contents


Getting Started

Maven Central

QuiFFT can be installed from the Maven Central Repository:

<dependency>
    <groupId>org.quifft</groupId>
    <artifactId>quifft</artifactId>
    <version>0.1.1</version>
</dependency>

Build from source

Alternatively, you can clone the project and build it from the command line:

$ git clone https://github.com/mhenrichs/QuiFFT.git
$ cd QuiFFT
$ mvn clean install

Supported File Types

QuiFFT's constructor accepts 8- and 16-bit audio files with the following extensions:

  • .wav
  • .aiff
  • .mp3

If a file not matching the above extensions or an audio file with a bit depth of 24 or 32 is provided, the constructor will throw an UnsupportedAudioFileException.

QuiFFT can perform FFTs on both single channel (mono) and dual channel (stereo) audio signals. For stereo audio, left and right samples are averaged together (which effectively converts it to mono) before computing the FFT.

QuiFFT Output Object Types

QuiFFT has been designed with simplicity and ease of use in mind, so its output structures are named using basic signal processing vocabulary and include metadata fields to make it extremely clear what type of information each object represents.

QuiFFT offers two methods to compute FFTs, the most straightforward of which is fullFFT(). The Full FFT reads the entire audio file into memory, then computes and stores each FFT frame (output of FFT applied to a single sampling window), finally returning an array of all FFT frames for the entire audio file when it completes. Typically the space complexity of this all-at-once computation won't be an issue, but if you're in a space-contrained environment or want to start using the results of each computed FFT frame right away, you'll want to take a look at fftStream(), which allows the computation of FFT frames one at a time.

FFTFrame

When computing a Fourier transform on an audio file, a prerequisite is to split the full-length waveform into multiple sampling windows (typically consisting of 2048, 4096, or 8192 samples each). The FFT algorithm is then applied to each of these sampling windows separately, producing a sequence of FFT frames that spans the duration of the entire audio file.

Therefore, the FFTResult object returned by quiFFT.fullFFT() includes an instance variable fftResult.fftFrames which points to an array of FFTFrame objects. Here's what an FFTFrame looks like:

class FFTFrame {
    double frameStartMs;
    double frameEndMs;
    FrequencyBin[] bins;
}

The frameStartMs and frameEndMs variables indicate the range of time from the original audio file represented in the sampling window used as input to this frame's FFT computation. The actual output of the Fourier transform is contained in the bins array.

FrequencyBin

The Fast Fourier Transform is based on the Discrete Fourier Transform, which separates the frequencies present in a signal into a finite set of discrete bins. For example, a frequency bin from 300 Hz to 320 Hz will indicate the cumulative power of all frequencies in the signal that fall between 300 Hz and 320 Hz.

Each FFTFrame contains an array of these FrequencyBins. Here's what a single FrequencyBin looks like:

class FrequencyBin {
    double frequency;
    double amplitude;
}

The frequency variable indicates the start (lower) value of the bin range in Hertz. The amplitude variable is what we're really interested in -- it represents the power of the frequencies within this bin from the time-domain sampling window. If you wanted to make a frequency spectrum visualizer, for example, the amplitude values of each FrequencyBin would lie along the y-axis of the spectrum graph. By default, amplitude values are in decibels (dB), but this can be changed through simple configuration of the FFT parameters.

Full FFT

The Full FFT is not an output object of QuiFFT, but instead one of two methods for computing FFTs. The Full FFT reads the entire audio file into memory, then computes and stores each FFT frame (output of FFT applied to a single sampling window), finally returning an array of all FFT frames for the entire audio file when it completes. As mentioned in the introduction to this setting, if you fear this all-at-once computation will violate space constraints, it would be preferable to use the FFT Stream method instead.

The output object associated with a full FFT is FFTResult. Here's what it looks like:

class FFTResult {
    // metadata inherited from FFTOutputObject
    String fileName;
    long fileDurationMs;
    double frequencyResolution;
    double windowDurationMs;
    FFTParameters fftParameters;
    
    // output structure unique to FFTResult
    FFTFrame[] fftFrames;
}

FFT output is accessible through the fftFrames array, which is a field unique to FFTResult.

FFT Stream

If you'd like to save some space by only reading bytes from an audio file as needed as opposed to all at once, the FFT Stream will come in handy. It's an alternative way to compute an FFT that, unlike the Full FFT, computes individual FFT frames on an as-requested basis.

The output object associated with an FFT stream is FFTStream. Here's what it looks like:

class FFTStream {
    // metadata inherited from FFTOutputObject
    String fileName;
    long fileDurationMs;
    double frequencyResolution;
    double windowDurationMs;
    FFTParameters fftParameters;
    
    // output methods unique to FFTStream
    boolean hasNext();
    FFTFrame next();
}

The FFTStream class extends Iterator<FFTFrame>, so you can call fftStream.hasNext() to check if there's another frame that can be computed, and fftFrame.next() to perform the sample extraction and FFT computation. The amount of work done by each call to next() is proportional to the window size chosen for the FFT.

Here's some code that obtains an FFTStream and computes FFT frames one at a time:

FFTStream fftStream = new QuiFFT("audio.mp3").fftStream();

while(fftStream.hasNext()) {
    FFTFrame nextFrame = fftStream.next();
    
    // do something with the computed frame here
}

FFT Streams can also be useful if you want to use FFT frames immediately after they are computed as opposed to waiting for all frames to be computed before taking any action.

A single instance of QuiFFT can produce either an FFTResult or an FFTStream, but not both. You should choose whether a Full FFT or an FFT Stream is preferable for your use case.

One thing to note: It is not allowed to compute values using an FFT Stream if the isNormalized parameter is set to true and the useDecibelScale parameter is set to false. If this is attempted, a BadParametersException will be thrown from fftStream(). This is because normalized output values only work if the maximum amplitude of any frequency bin across all frames is known, which is not the case for FFT Stream, which only knows the results of the current and previously computed frames.

Configuring FFT Parameters

The Fourier transform can be viewed as a single function with a number of parameters that can be configured to produce optimal results based on characteristics of the audio sample and the requirements of the spectral analysis being performed. QuiFFT uses method chaining to make configuration of these parameters straightforward.

Below is a reference for QuiFFT's configuration methods. None of these parameters are required to be explicitly set -- default values are denoted by boldface.

Method Description Values Constraints
.windowSize() Size of sampling windows from signal (number of samples per window) Integers (i.e. 512, 2048, 4096, 8192) Must be greater than 0, and if numPoints is not set, must be a power of 2
.windowFunction() Window smoothing function to be applied to the time domain signal prior to computing FFT WindowFunction.RECTANGULAR, WindowFunction.TRIANGULAR, WindowFunction.BARTLETT, WindowFunction.HANNING, WindowFunction.HAMMING, WindowFunction.BLACKMAN Cannot be null
.windowOverlap() Percentage by which consecutive windows will be overlapped (0.50 = 50% overlap) Decimal between 0.00 and 1.00 (0.50 by default) Must be greater or equal to 0 and less than 1
.numPoints() Number of points (N-point FFT); if set, each sampling window will be zero-padded up to the length designated by numPoints. This parameter can be useful if you want to use a window size that isn't a power of 2 -- simply set numPoints to the next power of 2 greater than your desired window size. Integers (equivalent to windowSize by default) Must be a power of 2
.dbScale() Boolean indicating whether FFT output should be represented in decibels (dB). On the dB scale, the highest possible amplitude a frequency bin can have is 0 dB (maximum energy) and the lowest is -100 dB (minimum energy) true, false If true, value of normalized doesn't matter because the decibels are, by definition, normalized
.normalized() Boolean indicating whether FFT output will be normalized such that each amplitude is in the range 0.00 - 1.00 where 1.00 represents the highest amplitude of any bin across the entire signal true, false Only applicable to full FFT (not FFT stream)

To get the current value of any of the above parameters from the QuiFFT object, simply call the configuration method without providing an argument.

FFT Algorithm Implementation

Under the hood, QuiFFT uses Robert Sedgewick and Kevin Wayne's implementation of an in-place radix 2 Cooley-Tukey FFT. It runs in O(n*logn) time.

JavaDoc and Code Examples

See QuiFFT's JavaDoc on its website: https://www.quifft.org/javadoc


Below are some code examples that make use of QuiFFT's functionality. All of these examples come from the quifft-examples repository.

Basic FFT with default settings

quifft-examples/yourfirstfft

FFT with customized parameters

  • FFT with rectangular windows of length 1024 samples and 75% window overlap
  • FFT whose amplitude values are scaled linearly (as opposed to logarithmic dB) between 0 and 1
  • FFT over sampling window that isn't a power of 2 (zero-padding)

quifft-examples/customizedparams

Music Frequency Spectrum Visualizer using FFTStream

This spectrum visualizer renders an animated graph of the frequency content of full-length MP3 files using QuiFFT's FFTStream and JFreeChart.

quifft-examples/spectrumvisualization

Changelog

  • v0.1.1: remove unnecessary Guava dependency -- read all bytes of an audio file using native classes [04/06/2019]
  • v0.1.0: initial release [04/05/2019]

quifft's People

Contributors

mileshenrichs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

quifft's Issues

small technical error at the start of the readme

The readme opens with "QuiFFT is a Fourier transform (FFT) library for digital audio files" but those two things are not the same. The Fourier Transform is just "FT" (with the discrete fourier transform being "DFT"). The acronym "FFT" is specifically and only for the "Fast Fourier Transform", a DFT that only works when the input data is constrained to powers-of-two windows, but works stupidly well with that constraint in place.

So it would be better to change that to either "QuiFFT is a Fourier transform (FT) library for digital audio files" with the wikipedia link that you're currently using, or "QuiFFT is a Fast Fourier transform (FFT) library for digital audio files" but then point to https://en.wikipedia.org/wiki/Fast_Fourier_transform instead.

Is FFTFrame giving the full Fourier Transform of one time-boxed section of the music, or one time-boxed part of the full Fourier Transform of the music?

The clarify: in my head there is a certain music track that I feed into this library. When I get an array of FFTFrames back, is each FFTFrame a Fourier Transform of the next, say, 1ms of the music? Or is each FFTFrame a 1ms chunk of the full Fourier Transform of the whole music? I guess a Fourier Transform would be different for 1ms of a song than for the whole song, so I'm confused which one this is. Thanks!

FFTStream.next() freezes

Hey! I'm trying to get a simple visualizer/renderer setup with this, though it seems to freeze every time I try to render a frame.

I set up this test;

FFTStream fftaStream = null;

try {
	fftaStream = new QuiFFT(audio).fftStream();
} catch (IOException | UnsupportedAudioFileException e1) {
	e1.printStackTrace();
}

System.out.println(fftaStream.fileDurationMs);

while (fftaStream.hasNext()) {
	System.out.println("b");
	System.out.flush();

	FFTFrame nextaFrame = fftaStream.next();

	System.out.println("c");
	System.out.flush();
}

to see if I could narrow down the issue, without much success.

(audio is a .wav File initialized earlier in the code)

The output consisted of the correct time in ms of the audio, and the letter "b".
No exceptions were thrown.
So in other words, the library grabbed the file correctly, and froze once it got to fftaStream.next();

Other info;
I'm currently using Mac OS
To use the library, I tried (separately)

  1. Adding the source code directly to the projects
  2. Compiling the source code myself and using the resulting .jar
  3. Downloading a precompiled .jar online, and using it

Any help would be greatly appreciated.

UnsupportedAudioFileException can not found

Hi,
Just now, I have import the lib from maven(org.quifft:quifft:0.1.1),
then there was a compile error in the Android Studio like : UnsupportedAudioFileException can not found.
image

Negative amplitude when using normalized - expected because of complex, or am I doing it wrong?

Strange that this comes out with negative amplitude. (I'm new, so I assume I'm goofing or misunderstanding)

    fftFrames.forEachIndexed { x, frame ->
        frame.bins.filter { humanHearing.contains(it.frequency.toInt()) }
            .forEachIndexed { y, bin ->
                check(bin.amplitude in 0.0..1.0) { "Normalized: ${fftParameters.isNormalized}, amplitude: ${bin.amplitude}" }
                val volumePct = bin.amplitude.coerceIn(0.0, 1.0).toFloat()
                println("amp: ${bin.amplitude} = $volumePct")
                val c = Color(volumePct, volumePct, volumePct)
                bi1.setRGB(x, y, c.rgb)
            }
    }

failed the check with
IllegalStateException: Normalized: true, amplitude: -22.516467467265123

PCMReader returning wrong fileDurationMs on 8 bit converted audio

Thanks for the library by the way, it's been super helpful!

If a file is 8bit, the PCMReader will properly convert to 16bit PCM. However, the PCMReader.getFileDurationMs method is calculating the duration based off the file size of the 8bit file but the frameSize and frameRate of the converted AudioFormat.

That method should use the encoded format instead of the decoded format to get the duration. The result is a final FFT with an incorrect number results by about half.

Lib implementation error

Hi, When I tried to implement the maven lib, there were two build errors like:


FAILURE: Build completed with 2 failures.

1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:mergeDebugJavaResource'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > More than one file was found with OS independent path 'javazoom/jl/decoder/lin2au.ser'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
==============================================================================

2: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:checkDebugDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
   > Duplicate class javazoom.jl.converter.Converter found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.Converter$PrintWriterProgressListener found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.Converter$ProgressListener found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.RiffFile found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.RiffFile$RiffChunkHeader found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.WaveFile found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.WaveFile$WaveFileSample found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.WaveFile$WaveFormat_Chunk found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.WaveFile$WaveFormat_ChunkData found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.WaveFileObuffer found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.jlc found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.converter.jlc$jlcArgs found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.BitReserve found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Bitstream found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.BitstreamErrors found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.BitstreamException found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Control found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Crc16 found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Decoder found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Decoder$Params found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.DecoderErrors found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.DecoderException found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Equalizer found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Equalizer$EQFunction found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.FrameDecoder found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Header found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.InputStreamSource found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.JavaLayerError found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.JavaLayerErrors found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.JavaLayerException found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.JavaLayerHook found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.JavaLayerUtils found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIDecoder found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIDecoder$Subband found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIDecoder$SubbandLayer1 found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIDecoder$SubbandLayer1IntensityStereo found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIDecoder$SubbandLayer1Stereo found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIDecoder found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIDecoder$SubbandLayer2 found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIDecoder$SubbandLayer2IntensityStereo found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIDecoder$SubbandLayer2Stereo found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIIDecoder found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIIDecoder$III_side_info_t found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIIDecoder$SBI found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIIDecoder$Sftable found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIIDecoder$gr_info_s found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIIDecoder$temporaire found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.LayerIIIDecoder$temporaire2 found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Manager found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Obuffer found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.OutputChannels found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.SampleBuffer found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.Source found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.SynthesisFilter found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.decoder.huffcodetab found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.AudioDevice found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.AudioDeviceBase found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.AudioDeviceFactory found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.FactoryRegistry found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.JavaSoundAudioDevice found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.JavaSoundAudioDeviceFactory found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.NullAudioDevice found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.Player found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.PlayerApplet found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.advanced.AdvancedPlayer found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.advanced.PlaybackEvent found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.advanced.PlaybackListener found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.advanced.jlap found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.advanced.jlap$1 found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.advanced.jlap$InfoListener found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     Duplicate class javazoom.jl.player.jlp found in modules jetified-jlayer-1.0.1 (javazoom:jlayer:1.0.1) and jetified-jlayer-1.0.1.4 (com.googlecode.soundlibs:jlayer:1.0.1.4)
     
     Go to the documentation to learn how to <a href="d.android.com/r/tools/classpath-sync-errors">Fix dependency resolution errors</a>.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.