private void PlayMetronome()
        {
            const int amp = 10000;
            double twopi = 8*Math.Atan(1.0);
            const double fr = 440.0;
            double ph = 0.0;

            int lastBpm = metronCurrentBpm;

            Animation anim = new AlphaAnimation(0.5f, 1.0f);
            anim.Duration = (60000/metronCurrentBpm)/2;
            anim.StartOffset = 0;
            anim.RepeatMode = RepeatMode.Reverse;
            anim.RepeatCount = Animation.Infinite;
            RunOnUiThread(() => { metronBpmText.StartAnimation(anim); });

            metronAudioTrack = new AudioTrack(Android.Media.Stream.Music, 44100, ChannelOut.Mono,
                Encoding.Pcm16bit, metronBuffSize, AudioTrackMode.Stream);

            metronAudioTrack.Play();

            while (reading)
            {
                Thread.Sleep(60000/metronCurrentBpm);

                if (lastBpm != metronCurrentBpm)
                {
                    // The BPM has changed - change the animation speed!
                    lastBpm = metronCurrentBpm;
                    anim.Duration = (60000/metronCurrentBpm)/2;

                    RunOnUiThread(() =>
                    {
                        metronBpmText.ClearAnimation();
                        metronBpmText.StartAnimation(anim);
                    });
                }

                for (int i = 0; i < metronAudioBuffer.Length; i++)
                {
                    metronAudioBuffer[i] = (short) (amp*Math.Sin(ph));
                    ph += twopi*fr/44100;
                }

                metronAudioTrack.Write(metronAudioBuffer, 0, metronAudioBuffer.Length);
            }

            metronAudioTrack.Stop();
            metronAudioTrack.Release();

            RunOnUiThread(() => { metronBpmText.ClearAnimation(); });
        }
        private void TransferSend()
        {
            CurrentTransferDataLeft = CurrentTransfer.FileLength;

            var at = new AudioTrack(Android.Media.Stream.Music,
                44100,
                ChannelConfiguration.Mono,
                Android.Media.Encoding.Pcm16bit,
                0x1000,
                AudioTrackMode.Stream);
            at.Play();

            // Polarity calibration header
            for (int i = 0; i < 200; i++)
            {
                WriteValue(at, BitConverter.GetBytes(-0x7fff), Bitlen);
                WriteValue(at, BitConverter.GetBytes(0x7fff), Bitlen * 3);
            }

            // Lead-in
            for (int i = 0; i < 20; i++)
                PutByte(at, 0xff);

            // Sync sequence
            for (byte i = 0x08; i >= 0x04; i--)
                PutByte(at, i);

            // Data
            byte[] buf = new byte[1];
            while (CurrentTransferDataLeft > 0 && !AbortCurrentTransfer)
            {
                CurrentTransfer.GetData(buf);
                PutByte(at, buf[0]);

                CurrentTransferDataLeft--;
            }

            at.Stop();
            at.Release();
            at.Dispose();

            CurrentTransfer.Close();

            ParentConnection.RaiseFileTransferEnded(CurrentTransfer, true, AbortCurrentTransfer);
        }