is there anyway to play a file that is being dynamically added to, using android media player ?
I tried using RandomAccessFile :
public static RandomAccessFile tempMp3;
tempMp3 = new RandomAccessFile(Environment.getExternalStorageDirectory()+"/ggg", "rw");
StaticData.tempMp3.setLength(file_size);
StaticData.tempMp3.seek(0);
//Here I call the auto update function and after X bytes are written I call playMediaPlayer
StaticData.mediaPlayer.setDataSource(StaticData.tempMp3.getFD());
StaticData.mediaPlayer.prepare();
StaticData.mediaPlayer.start();
So basically I am updating and playing at the same time.
The problem is that MediaPlayer and my Update function both are accessing and moving the file pointer, which messes up the MediaPlayer.
Is there any workaround ?
Can I use separate file pointers ?
Solved this.
Java NIO to the rescue.
Using memory-mapped IO, we can write to our file, without disturbing the file pointer, so the android media player is happy. Here is a helpful link.
The trick is to set the size of our MappedByteBuffer = size of music file.
We also need to ensure that the media player pauses if we have not yet written to the buffer. This can be achieved by monitoring the file-pointer.
Related
I'm creating an app in which multiple devices can connect to each other in a LAN and play songs from each other's device.
Right now, when device A requests a song from device B, B sends the song file back to A over a socket. Once the song finishes downloading, A starts playing it using MediaPlayer.
Now the problem with this is that even on a high speed LAN, it can take a couple of seconds to finish fetching the song, so there's a noticeable delay between selecting a song and it's playback actually starting.
I want to find a way to play a song while it's still being downloaded. Here are some possible solutions I found, but wasn't able to explore for certain reasons:
In the MediaPlayer documentation, I noticed a constructor that takes a MediaDataSource implementation allowing me to manually return parts of the media file whenever the MediaPlayer requires it so I could hold off returning a byte until it finishes downloading (if it hasn't finished downloading already), effectively acting like a "buffering" action. It seemed like a solution but unfortunately, my app's minSdk is set to 16 and MediaDataSource is for 23 and above only, so I couldn't try it out.
One option was to use MediaPlayer's setDataSource(FileDescriptor fd, long offset, long length) method. This would allow me to tell the MediaPlayer to only play up to a certain byte of the song. That way, I could wait for more parts of the file (or the entire file) to become available, and then use setNextMediaPlayer() and pass in a new MediaPlayer object that prepares the entire song and is made to seek up to the point where the previous media player object will stop playing so that there's a seamless transition.
But there's another problem with this. I need to be able to calculate the millisecond position that would be reached at that last specified byte of the first incomplete media player object. Otherwise I wouldn't know what position to seek the next media player object to in order to get a seamless transition. This calculation seems impossible for lossy formats.
I don't really know if this option will work or not, I'm just making assumptions. I noticed that setDataSource() takes a Uri. If that Uri points to a file on the phone, the media player just loads the entire file. But if the Uri points to an audio file on the internet that needs to be streamed, it figures that out on it's own and it handles all the details of downloading and buffering. So what I want to know is, is it possible to expose the song on device B as a Uri to device A so that media player just treats it as if it's a song on the internet? All this time I was using sockets and manually copying a file from one device to another so I have no idea how this would work. Could anyone explain if this is possible?
There's actually a reason why I haven't been exploring ways to "stream" a song from one device to another. That's because I want to song to be cached on device B so that later if I switch to another song and then back the previously played song from device A, it shouldn't have to stream it again. It should just play the cached copy.
Finally, I came across ExoPlayer. It seems to provide a large amount of customization. It seems like I could make custom implementations of it's classes to handle all the buffering. But the documentation and examples are few and far too complicated for me. I have no idea how to pull it off. Is this solution too complex for what I want to achieve?
Hope someone can point me in the right direction here.
Ended up using an answer from here:
MediaPlayer stutters at start of mp3 playback
This solution sets up a local server that the MediaPlayer can use to stream the file. The server only sends bytes to the MediaPlayer while those bytes are available. Otherwise, it blocks until more bytes are available. Thus the MediaPlayer buffers it as if it were a file from a web server.
I took the same class provided in that answer and just tweaked it to fit my situation.
I've been working on a really simple mp3 player in java for some weeks now and I'm wondering if I can do playlist with a BufferedReader and BufferedWriter method. For example with JFileChooser I'd choose song and store its path to file (for example "playlist.txt") and then in while loop (BufferedReader.available()) I'd read path and play it. Is this possible? Or Is it better to set chooser.setMultiSelectionEnabled() to true and work in this direction?
Seems like the best solution for this would be making a BufferedReader over the FileReader to read the file. Then you can make java.io.File objects and put those into a java.util.ArrayList. Then you can get the files easily from from the ArrayList and dispose the readers. You can also add an refresh method to refresh the list if needed.
What I did was use a for loop like this:
File playlist = new File("U:\\186Project\\Project\\data");
for(File f : playlist.listFiles()){
song = minim.loadFile(f.getName(), 2048);
......
}
I was using Processing to make LEDs light up to the beat of music, if you want to check out the full code out go here.
This won't let you choose certain songs but it does cycle through them like a playlist. Make sure to change "U:\186Project\Project\data" to whatever directory has all your MP3 files in it.
Im trying to get the duration of a Music, in libgdx
Im not talking about :
getPosition();
What I want is the Duration of the music. (in seconds)
Thanks
To be clear by "duration" you mean the total time the music would play without looping.
I don't think the Libgdx sound APIs expose this (the lowest common denominator sound API across desktop, Android and Web is pretty low ...).
You may be able to get this information out of the files you're loading into system, though (e.g., if they're wav or mp3 files there should be APIs to query their duration).
Its an old question but I will give my answer for the future visitors
To get the duration of a music file you can use the gdx-audio extension.
FileHandle file=Gdx.files.internal(filepath);
FileHandle external=Gdx.files.external("mygame/"+filepath);
if(!external.exists())file.copyTo(external); //copy the file to the external storage
Mpg123Decoder decoder = new Mpg123Decoder(external);
System.out.println("name:"+filepath+" duration:"+decoder.getLength());
if ur looking to stop the music when u want then by using
music.stop();
or pause the music by
music.pause();
or for other tasks refer to this link https://github.com/libgdx/libgdx/wiki/Streaming-music
I'm developing an application that necessitates the use of sound files (through the JLayer audio library at the moment) and am wondering if it is possible to cache a file in memory so that it doesn't have to be read off of the hard disk every time it's needed.
For example, I can store an image in a BufferedImage object instead of calling ImageIO.read every time I need an image; is there a similar way to approach this using JLayer? Should I use a different audio library? I just don't want to be hitting the disk every time the user triggers a sound (potentially many times per second).
If it makes a difference, the audio is in MP3 format.
You can read any file (up to a certain size) into a byte[] and process it from there.
Java's abstraction of InputStreams (where the consumer need not know where the data is from) should make this very straightforward (assuming your audio library is not hard-coded to read from files).
Start by looking up ByteArrayOutputStream and ByteArrayInputStream.
If any of my fellow Xuggler users can tell me what I'm doing wrong, that would be awesome! I am doing the following:
Reading from ogv (ogg video)
Queueing the audio and video
Writing back to ogv
sounds simple right? The problem I am experiencing in my QueueMixer class is that the output file plays the audio 2x too fast, and no matter what I check or change with regards to pts it doesnt improve.
The eclipse project and all files being used are at this link:
http://dl.dropbox.com/u/7316897/paul-xuggled.zip
To run a test, compile and execute the StreamManager class; a test ogv file is included. Before anyone asks, yes I have to queue the data as it will be mixed with other data in a future version.
Audio has a sample rate. Make sure that you copy the sample rate from the input to the output, otherwise the system might use a default (like 44KHz while the original data was sampled at 22KHz which would create such an effect).
The fix is to multiply the sample count by two when extracting them from the ShortBuffer.
samples = new short[(int) audioSamples.getNumSamples() * 2];
audioSamples.getByteBuffer().asShortBuffer().get(samples);
Having half the samples causes the audio to play twice as fast.