I have re-created a MIDI file without altering any of its Meta events. I have merely added SysEx (System Exclusive) messages under each note_on and note_off event. I use this library to parse MIDI files and extract tracks in order to get the MIDI messages.
Following is some sample code that I have tried (I have the MIDI file inside the raw folder).
try {
InputStream is = getResources().openRawResource(R.raw.mysamplemidifile);
File tempFile = File.createTempFile("temp", ".mid");
tempFile.deleteOnExit();
FileOutputStream out = new FileOutputStream(tempFile);
IOUtils.copy(is, out);
MidiFile midi = new MidiFile(tempFile);
ArrayList<MidiTrack> tracks = midi.getTracks();
MidiTrack sysExTrack = tracks.get(tracks.size() - 1);
} catch (Exception e) {
e.printStackTrace();
}
Originally the total number of MIDI messages is ~2500. But the library is able to fetch only about 2300 MIDI messages.
The sysExTrack variable contains the incompletely parsed SysEx data.
I am at a loss to understand what is going wrong here. Any help with the same is appreciated.
Edit:
The MIDI file gets parsed correctly in iOS.
Related
I want to read the content of the .mp3 file into a byte array(Not including header and metadata). For this purpose I'm using following code.
File myFile = new File("C:\\Users\\Kaushal28\\Desktop\\a.mp3");
byte[] samples;
AudioInputStream is = AudioSystem.getAudioInputStream(myFile);
DataInputStream dis = new DataInputStream(is); //So we can use readFully()
try{
AudioFormat format = is.getFormat();
samples = new byte[(int)(is.getFrameLength() * format.getFrameSize())];
dis.readFully(samples);
}
finally{
dis.close();
}
Here is the link where it is posted: Here.
I executed this code with a mp3 file of a song. but got following exception:
javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file
I've also tried this with .au file type, but got same exception.
For this I searched on Internet and found this: This SO link.
It says that all wav formats are not supported by java. Is it also true for .mp3 file formats? Or any other reasons due to which I'm getting this exception?
As I see at MediaMetadataRetriever API, there are constants for the common tags.
In my app I want to read all the mp3 tags. In order to do this I use jid3lib.
When I tried to read tags without any connection to android (MP3 files on my computer), I succeeded, but when I tried to read MP3 files on the emulator my application crashed.
I pushed some music files into the emulator, and I succeeded in reading these files names, but when the application is trying to get the tags it crashed.
I wonder if there is any android permission that I have to declare in the manifest? Or maybe there is difference between reading files on the local computer and in android? because I use the same logic to read MP3 files on my computer and it works.
EDIT : Code from comment below for better readability
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
File[] songs = path.listFiles();
for (int i=0; i<songs.length; i++){
try {
MusicFile song = new MusicFile(songs[i]);
Log.d("VanVan", song.getArtist());
} catch (TagException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
i want to store a H264 video that is recorded from a rtp (live)stream to a file.
i've tried this with a simple java program, but vlc player cannot open the file.
here is my code:
try
{
socket = new DatagramSocket(port);
fos = new FileOutputStream(filePath + outputFileName);
do
{
DatagramPacket in = new DatagramPacket(inData, inData.length);
socket.receive(in);
byte[] bytes = in.getData();
if (curPos < buffer.length)
{
for (int i = 0; i < bytes.length; i++)
{
buffer[curPos] = bytes[i];
curPos++;
if (curPos >= buffer.length)
{
receivePackets = false;
break;
}
}
}
else
{
receivePackets = false;
}
Thread.sleep(SOCKET_TIMEOUT);
}
while (receivePackets);
fos.write(buffer, 0, buffer.length);
if (fos != null)
{
fos.close();
}
if (socket != null)
{
socket.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
the file will be created, but it's not possible to open it.
are there any header informations i've to cut of or add to the byte array to get a correct video file?
UPDATE:
ok, the problem seems to be the nal header information of the h264 rtp packet, because i can open a recorded h263 video with a standard rtp header (but the quality of the video is really bad).
Rtp has headers in their packets that aren't part of the h264 stream, as well as has mechanics for splitting one nal unit (essentially a single h264 "packet") over multiple packets or merging multiple nal units into one packet, both of which add metadata that can't be a part of the final product.
Additionally, the RTP stream may not contain some of the metadata necessary to play the video, especially if its negotiated over rtsp. If that's the case you'll have to pull some NAL units out of the sprop-parameter-sets in the SDP.
You can find the documentation on how all of that works here: https://www.rfc-editor.org/rfc/rfc6184. It's really not as hard as it sounds.
When h264 is written to a file, each nal unit must be preceded by three 0 bytes and then a 1 byte. You can find more details on that here: https://www.itu.int/rec/T-REC-H.264-201906-I/en
VLC has to be talked into playing raw h264 files. You can google that and find easy steps to do so, its not related to the code so I won't copy them here.
If you want the file as a mp4, your best using a library to do this. If you want to do it all yourself, heaven help you, but you can find the spec here: https://web.archive.org/web/20180921052457/http://l.web.umkc.edu:80/lizhu/teaching/2016sp.video-communication/ref/mp4.pdf. The https://github.com/sannies/mp4parser library is java and may do that but, has some issues. Ffmpeg is a wonderful program to do this, and I've had luck running it as a subprocess to Java and feeding its standard in and reading from its standard out.
As a side note, ffprobe is a great program, running it on a broken video file can provide some insight on what's wrong with it.
You have to unpack the video data from RTP packets
I have a problem about streaming my video to server in real-time from my phone.
that is , let my phone be a IP Camera , and server can watch the live video from my phone
I have googled many many solutions,
but there is no one can solve my problem.
I use MediaRecorder to record .
it can save video file in the SD card correctly.
then , I refered this page and used some method as followings
skt = new Socket(InetAddress.getByName(hostname),port);
pfd =ParcelFileDescriptor.fromSocket(skt);
mediaRecorder.setOutputFile(pfd.getFileDescriptor());
now it seems I can send the video stream while recording
however, I wrote a receiver-side program to receive the video stream from Android ,
but it doesn't work . is there any error?
I can receive file , but I can not open the video file .
I guess the problem may caused by file format ?
there are outline of my code.
in android side
Socket skt = new Socket(hostIP,port);
ParcelFileDescriptor pfd =ParcelFileDescriptor.fromSocket(skt);
....
....
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setOutputFile(pfd.getFileDescriptor());
.....
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
.....
mediaRecorder.start();
in receiver side (my ACER notebook)
// anyway , I don't think the file extentions will do any effect
File video = new File (strDate+".3gpp");
FileOutputStream fos;
try {
fos = new FileOutputStream(video);
byte[] data = new byte[1024];
int count =-1;
while( (count = fin.read(data,0,1024) ) !=-1)
{
fos.write(data,0,count);
fos.flush();
}
fos.close();
fin.close();
I confused a long time....
thanks in advance
Poc,
The way MediaRecorder writes files is as follows:
Leave space for empty header
Write file contents while recording
When recording finishes, seek to the beginning of file
Write the header at the beginning of the file
Then (I believe) there is another seek to the end of the file where metadata is written.
Because there is no concept of "seeking" on a socket, you will have to figure out when the header comes, seek to the beginning of your file, and then write the header in the appropriate location.
The best place to start here is to use a hexeditor to determine the format of a valid 3gpp file, then analyze this hex against your receiver program's hex output. Also you will want to look into 3gpp file formats.
I'm analyzing music mp3 files. What I'm doing is extracting the audio data from the file and computing music similarity.
I've been using javazoom in order to handle mp3 files. By using audioFormat I'm extracting the raw data from the mp3 file:
byte[] audioBytes = new byte[numBytes];
in_format_init = AudioSystem.getAudioInputStream(musicFile);
AudioFormat formatInit = in_format_init.getFormat();
AudioFormat formatFinal = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
formatInit.getSampleRate(),
16,
formatInit.getChannels(),
formatInit.getChannels()*2,
formatInit.getSampleRate(),
false);
AudioInputStream streamIn = AudioSystem.getAudioInputStream(formatFinal, in_format_init);
while (((numBytesRead = streamIn.read(audioBytes)) != -1))
{...}
By doing this I store the audio data (without headers or tags) in audioBytes and then the info stored in the array is processed.
My question is: is it posible to extract the audio information from an mp3 audio file and store it as I do it in my example? I've been reading about JMF, but it's confusing for me.
Thanks.
I've just had a quick look at the JMF API so I'm not a 100% sure this will be correct or even work at all, but try something like this:
try {
File f = new File ("/path/to/my/audio.mp3");
DataSource ds = Manager.createDataSource(f.toURI().toURL());
ds.connect();
ds.start();
...
} catch (java.io.IOException e) {
...
} catch (NoDataSourceException e) {
...
}
After this try getting the controls from the DataSource: ds.getControls(), and see if any of the controls allows you to read the raw audio data.
You'll probably have to do all kinds of cleanup as well, e.g. ds.disconnect(), after you're done reading the audio.
Also, don't forget to install the JMF MP3 plugin
-- Lauri