0

I need to play a custom generated sound from my Xamarin app for android. My current code looks like this:

    public class NotePlayer {
        private const int sampleRate = 44100;
        private const int bufferSize = 22050;
        private Task<AudioTrack> track = null;
        public double Frequency { get; private set; }

        public NotePlayer(double frequency) {
            this.Frequency = frequency;
        }

        public void Play() {
            short[] source = new short[bufferSize/2];
            for(int i= 0; i<source.Length; i++) {
                source[i] = (short)(Math.Sin(((double)i) / sampleRate * Frequency* Math.PI*2)*Int16.MaxValue);
            }
            var track = new AudioTrack(Stream.Music, sampleRate, ChannelOut.Mono, Android.Media.Encoding.Pcm16bit, bufferSize, AudioTrackMode.Static);
            track.Write(source, 0, bufferSize);
            track.SetLoopPoints(0, bufferSize / 2, -1);
            track.Play();
            this.track = Task.FromResult(track);
        }

        //Some more methods here
}

The problem is that I keep getting Java.Lang.IllegalStateException: play() called on uninitialized AudioTrack. exception on the line track.play().

I have seen this question, from where I understood that I might have to do something with the endianity of my samples, but that shouldn't matter at this point and also the code in the accepted answer looks almost exactly like my example, which confuses me even more. Even tried commenting out the SetLoopPoints line to make it look exactly alike, didn't help.

Tested on android 5.1.

Viki
  • 25
  • 6

1 Answers1

0

The cause of your problem is that your track's state is AudioTrackState.NoStaticData.

You've created a source with length bufferSize / 2, but when you write the source to AudioTrack, you tried to write the data with length bufferSize, the data is not complemented.

Just change your code track.Write(source, 0, bufferSize); to track.Write(source, 0, source.Length);.

Grace Feng
  • 16,564
  • 2
  • 22
  • 45