I've a problem in converting byte to .mp3 sound file. In my case I do it using FileOutputStream using its write(bytes) method but it just creates a data file with mp3 extension but I cannot play it in any player on my PC.
Note: I'm recording it from Flex Michrophone and send ByteArray to java.
Which libraries should I use to add mp3 sound file headers etc. in java?
UPDATE: I couldn't even convert my raw data to Wave format that is supported by java sound api.. It creates for me sound with recorded sound but with a noise - where's the problem?
Here's my code for wave:
AudioFormat format = new AudioFormat(Encoding.PCM_SIGNED, 44100, 16, 2, 2, 44100, true);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
AudioInputStream stream = new AudioInputStream(bais, format, bytes.length/format.getFrameSize());
AudioSystem.write(stream, AudioFileFormat.Type.WAVE, new File(path+"zzz.wav"));
What's wrong with my AudioFormat??? And which one do I have to use in MP3 case ?!
Urgent help! Any help will be highly appreciated!
Just writing the raw bytes to a file with the name extension .mp3 doesn't magically convert the data to the MP3 format. You need to use an encoder to compress it.
A quick google search found LAMEOnJ which is a Java API for the popular LAME MP3 encoder.
Related
I'm working on a system to play, pause and stop music. I'm testing this out with 2 different wav files, one with a length of 45 seconds and other with a length of 3:35 minutes. The problem I'm having is that the 45 second wav file plays without any problem. The 3:35 minute wav file on the other hand, doesn't load. Is there a maximum time limit to wav files in java or is it possible the wav file is broken? It plays without any problem on windows app "groove music".
I've searched around on stack overflow but no one seemed to experience the same problem as I am, one wav file playing, the other one not.
Error code I'm getting:
javax.sound.sampled.LineUnavailableException: line with format PCM_FLOAT 44100.0 Hz, 32 bit, stereo, 8 bytes/frame, not supported.
The method i use for playing the wav file.
public static void playAudio(String name) {
try {
System.out.println("NOTE: Playing audio");
clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(
Engine.class.getResourceAsStream("/Audio/" + name));
clip.open(inputStream);
clip.start();
} catch(Exception e) {
System.out.println("ERROR: Failed to load audio");
}
}
Calling the method
Engine.playAudio("easy2.wav");
Picture of the wav files in the "src/Audio/" folder
Given the error message, one thing you could try is after opening the AudioInputStream from the resource, do the following:
AudioFormat fmt = inputStream.getFormat();
fmt = new AudioFormat(fmt.getSampleRate(),
16,
fmt.getChannels(),
true,
true);
inputStream = AudioSystem.getAudioInputStream(fmt, inputStream);
This attempts to convert the stream away from a floating-point format, hopefully to something that the system is more likely to support. (Also see JavaDoc for AudioSystem.getAudioInputStream(AudioFormat, AudioInputStream).)
You can run the following code to find out what formats are likely available for playback:
Arrays.stream(AudioSystem.getSourceLineInfo(new Line.Info(SourceDataLine.class)))
.filter(info -> info instanceof DataLine.Info)
.map(info -> (DataLine.Info) info)
.flatMap(info -> Arrays.stream(info.getFormats()))
.forEach(System.out::println);
If the above method of converting the audio stream doesn't work, then probably your best bet is to just convert the file with some editor, such as Audacity. Java sound is unfortunately still pretty limited in what formats it supports by default. (The most reliable format is probably CDDA, which is 44100Hz, 16-bit signed LPCM.)
There may also be 3rd-party SPIs which support conversions from floating-point PCM.
The problem I was facing originated in the wav file itself. Since a wav file can have one of several different formats, the one it was encoded with was not compatible with java. The solution was to change the bitrate and Hz of the wav file to match an encoding that java supported.
More about wav formats: https://en.wikipedia.org/wiki/WAV
I have mp3 files I'd like to run through Google's Cloud Speech API [reference] - but just the first 15 seconds of each audio file. I'm working in Scala with jlayer, mp3spi, and tritonus libraries imported as suggested by JavaZoom. My code so far looks like this:
val in = AudioSystem.getAudioInputStream(new URL("mySong.mp3"))
val baseFormat = in.getFormat
val decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
16000,
16,
baseFormat.getChannels,
baseFormat.getChannels * 2,
16000,
false)
val audioInputStream = AudioSystem.getAudioInputStream(decodedFormat, in)
val buffer = new Array[Byte](16000*4*15)
var i = 0
while (audioInputStream.available() > 0) {
i += audioInputStream.read(buffer)
}
audioInputStream.close()
in.close()
// pass this to API request:
lazy val recognitionConfig: RecognitionConfig = RecognitionConfig.newBuilder
.setEncoding(AudioEncoding.LINEAR16)
.setLanguageCode("en-US")
.setSampleRateHertz(16000)
.build
val request = RecognizeRequest.newBuilder()
.setAudio(RecognitionAudio.newBuilder().setContent(ByteString.copyFrom(buffer)).build())
.setConfig(recognitionConfig)
.build()
However, when I print out the value of the ByteString-copied buffer it's only 0's and the API call returns nothing. Any ideas on what I'm doing wrong? this is my first time manipulating audio in Java/Scala so I may be missing something obvious...
I had the same problem. You get nothing if the audio is not intelligible or is encoded in a format but not decoded appropriately, and other specifics e.g. th audio file can't be stereo, it needs to be mono.
So I first converted the audio from .mp3 to .flac as follows using the ffmpeg module (in python - you need to find its scala version):
# turn the video into audio
ff = ffmpy.FFmpeg(inputs={input_file_path: None}, outputs={output_file_path: '-y -vn -acodec flac -ar 16000 -ac 1'})
ff.run()
the input_file_path and the out_file_path are strings that contain paths for the input and output audio file locations. Note: you can test the output audio file to see if the conversion was successful using the play command.
Having done the above, you can now use AudioFormat.Encoding.FLAC and AudioEncoding.FLAC instead.
I successfully stream audio over TCP from python running on raspberry pi to an android application and I am trying to use compression but it's only working with strings and not working with data from audio stream (only noise is heard)
here is my python code:
while True:
data = stream.read(CHUNKS)
outData = StringIO()
d = GzipFile( mode="w", fileobj = outData)
d.write(data)
d.close()
conn.send((outData.getvalue()))
and my android code:
speaker = newAudioTrack(AudioManager.STREAM_VOICE_CALL,sampleRate,channelConfig,audioFormat,minBufSize,AudioTrack.MODE_STREAM);
speaker.play();
DataInputStream ds = new DataInputStream(connectionSocket.getInputStream());
GZIPInputStream gzip = new GZIPInputStream(ds);
while (true) {
gzip.read(buffer, 0, buffer.length);
speaker.write(buffer, 0, buffer.length);}
Does anybody have an idea why this is not working? Also, are there alternative ways to achieve what I'm trying to?
The problem might not be in GZIP at all:
AudioTrack used only for uncompressed audio as mentioned here:
It allows streaming of PCM audio buffers to the audio sink
You might give the MediaPlayer a try, as an example:
MediaPlayer player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource("http://...");
player.prepare();
player.start();
Yet this might not be what you need as you are trying to use Socket
In this case you might use Temporary file as mentioned in this post
OR use a Local HTTP server to stream an InputStream to MediaPlayer on Android
Hope this can help, best of luck :)
I have encrypted an audio file (.wav, .midi, .au, .mid) and want to decrypt it and play the audio without storing it to disk. I have a bytearray after decrypting the audio file, and now I have to play it.
My problem is how to find the audio format from this resulted bytearray and play it.
byteoutput=new byte[(int) fileSize];
In my Android application I am recording the user's voice which I save as a .3gp encoded audio file.
What I want to do is open it up, i.e. the sequence x[n] representing the audio sample, in order to perform some audio signal analysis.
Does anyone know how I could go about doing this?
You can use the Android MediaCodec class to decode 3gp or other media files. The decoder output is standard PCM byte array. You can directly send this output to the Android AudioTrack class to play or continue with this output byte array for further processing such as DSP. To apply DSP algorithm the byte array must be transform into float/double array. There are several steps to get the byte array output. In summary it looks like as follows:
Instantiate MediaCodec
String mMime = "audio/3gpp"
MediaCodec mMediaCodec = MediaCodec.createDecoderByType(mMime);
Create Media format and configure media codec
MediaFormat mMediaFormat = new MediaFormat();
mMediaFormat = MediaFormat.createAudioFormat(mMime,
mMediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE),
mMediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT));
mMediaCodec.configure(mMediaFormat, null, null, 0);
mMediaCodec.start();
Capture output from MediaCodec ( Should process inside a thread)
MediaCodec.BufferInfo buf_info = new MediaCodec.BufferInfo();
int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(buf_info, 0);
byte[] pcm = new byte[buf_info.size];
mOutputBuffers[outputBufferIndex].get(pcm, 0, buf_info.size);
This Google IO talk might be relevant here.