Is there a way to stream bytes directly to Android.Media.MediaPlayer? So when I receive a bunch of bytes I can throw them to this class and play them and repeat? I couldn't find any examples of feeding MediaPlayer with bytes and it seems like the most reasonable approach.
Currently I'm playing around with storing each packet as a temporary file, so I can play a small portion of music and dispose it right away, but I haven't gotten it to work yet and it feels like a terrible approach.
This is what I've tried so far. I receive a small portion of sound (bArray) and I append .wav header to it so that I can play it. I do this with each packet I receive. This header matches the data I receive (I use NAudio library to record sound):
public void PlayAudio(byte[] bArray)
{
var player = new MediaPlayer();
player.Prepared += (sender, args) =>
{
player.Start();
};
var header = new byte[]
{
0x52, 0x49, 0x46, 0x46, // b Chunk ID (RIFF)
//0x24, 0xDC, 0x05, 0x00, // l Chunk size
0x32, 0x4B, 0x00, 0x00,
0x57, 0x41, 0x56, 0x45, // b Format WAVE
0x66, 0x6d, 0x74, 0x20, // b Subchunk 1 id
0x12, 0x00, 0x00, 0x00, // l Subchunk 1 size (size of the rest of the header) = 16
0x03, 0x00, // l Audio format, 1 = Linear Quantization, others = compression
0x02, 0x00, // l Number of channels, 1 = mono, 2 = stereo
0x80, 0xBB, 0x00, 0x00, // l Sample rate
0x00, 0xDC, 0x05, 0x00, // l Byte rate (SampleRate * NumChannels * BitsPerSample / 8)
0x08, 0x00, // l Block align (NumChannels * BitsPerSample / 8)
0x20, 0x00, // l Bits per sample
0x00, 0x00, 0x66, 0x61, // compression data
0x63, 0x74, 0x04, 0x00, // compression data
0x00, 0x00, 0x60, 0x09, // compression data
0x00, 0x00, // compression data
0x64, 0x61, 0x74, 0x61, // b Subchunk 2 id (Contains the letters "data")
0x00, 0x4B, 0x00, 0x00, // l Subchunk 2 Size
};
var file = File.CreateTempFile("example", ".wav");
var fos = new FileOutputStream(file);
fos.Write(header);
fos.Write(bArray);
fos.Close();
player.Reset();
var fis = new FileInputStream(file);
player.SetDataSource(fis.FD);
player.Prepare();
}
Obviously this code is not optimized, but I cannot even get it to work and I've spent a lot of time on it, so hopefully there is a different solution to this problem.
As far as I know, MediaPlayer cannot play continous stream (was not designed for that). However, there is more low-level class, AudioTrack, which is capable of doing that.
Here is small sample from one of my projects:
private int _bufferSize;
private AudioTrack _output;
// in constructor
_bufferSize = AudioTrack.GetMinBufferSize(8000, ChannelOut.Mono, Encoding.Pcm16bit);
// when starting to play audio
_output = new AudioTrack(Stream.Music, 8000, ChannelOut.Mono, Encoding.Pcm16bit, _bufferSize, AudioTrackMode.Stream);
_output.Play();
// when data arrives via UDP socket
byte[] decoded = _codec.Decode(decrypted, 0, decrypted.Length);
// just write to AudioTrack
_output.Write(decoded, 0, decoded.Length);
Of course you need to understand what all those parameters mean (like Pcm16bit or sample rate) to implement it correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With