Опубликован: 01.11.2011 | Доступ: свободный | Студентов: 1424 / 63 | Оценка: 3.84 / 3.44 | Длительность: 15:38:00
Специальности: Программист
Практическая работа 22:

Работа с микрофоном

Аннотация: В данной работе мы продемонстрируем возможность записи и воспроизведения звука

Дополнительные материалы к занятию можно скачать здесь.

Упражнение 32.1. Знакомство с микрофоном

В данной работе мы познакомимся с возможностью записи и воспроизведения звука (пример предоставлен Microsoft http://msdn.microsoft.com/en-us/library/gg442302(v=VS.92).aspx).

Создаем новое приложение Windows Phone 7 practice_22_1. Добавляем ссылку на библиотеку Microsoft.Xna.Framework


К проекту нужно добавить папку Images: Solution Explorer -> Имя проекта -> Add -> New Folder -> Images


В папку нужно поместить небольшие изображения приведенные ниже, назвав их blank.png, microphone.png, play.png, record.png, speaker.png и stop.png.


Затем нужно правой кнопкой мыши щелкнуть по папке Images, выбрать пункты Add -> Existing Item -> Выбрать наши изображения -> Add.


После этого нужно внести изменения в файл MainPage.xaml:

<!-- 
    Copyright (c) 2010 Microsoft Corporation.  All rights reserved.
    Use of this sample source code is subject to the terms of the Microsoft license 
    agreement under which you licensed this sample source code and is provided AS-IS.
    If you did not accept the terms of the license agreement, you are not authorized 
    to use this sample source code.  For the terms of the license, please see the 
    license agreement between you and Microsoft.
-->
<phone:PhoneApplicationPage 
    x:Class="SilverlightMicrophoneSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="MainPanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="Работа с микрофоном"
             Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="UserHelp" Text="Нажмите запись" Margin="9,-7,0,0"
             Style="{StaticResource PhoneTextTitle1Style}" Height="200" FontSize="56" />
        </StackPanel>
        <Image x:Name="StatusImage" Grid.Row="1" Height="334" Width="366" 
               HorizontalAlignment="Center" VerticalAlignment="Center"
               Source="Images/blank.png" Margin="61,0,53,97" />
        <!--ContentPanel - place additional content here-->
    </Grid>

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <shell:ApplicationBar.Buttons>
                <shell:ApplicationBarIconButton x:Name="recordButton" Text="record" IconUri="/icons/record.png" 
                 Click="recordButton_Click" IsEnabled="True"/>
                <shell:ApplicationBarIconButton x:Name="playButton" Text="play" IconUri="/icons/play.png"
                   Click="playButton_Click" IsEnabled="False"/>
                <shell:ApplicationBarIconButton x:Name="stopButton" Text="stop" IconUri="/icons/stop.png"
                  Click="stopButton_Click" IsEnabled="False"/>
            </shell:ApplicationBar.Buttons>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

</phone:PhoneApplicationPage>
    

и в файл MainPage.xaml.cs:

/* 
    Copyright (c) 2010 Microsoft Corporation.  All rights reserved.
    Use of this sample source code is subject to the terms of the Microsoft license 
    agreement under which you licensed this sample source code and is provided AS-IS.
    If you did not accept the terms of the license agreement, you are not authorized 
    to use this sample source code.  For the terms of the license, please see the 
    license agreement between you and Microsoft.
*/
using System;
using System.IO;
using System.Threading;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

namespace SilverlightMicrophoneSample
{
    public partial class MainPage : PhoneApplicationPage
    {
        private Microphone microphone = Microphone.Default;     // Объектное представление физического микрофона в устройстве
        private byte[] buffer;                                  // Динамический буфер для получения аудио данных с микрофона
        private MemoryStream stream = new MemoryStream();       // Сохраняет аудиоданные для последующего воспроизведения
        private SoundEffectInstance soundInstance;              // Использоан для воспроизведения аудио
        private bool soundIsPlaying = false;                    // Флаг для мониторинга состояния воспроизведения аудио

        // Изображения статуса
        private BitmapImage blankImage;
        private BitmapImage microphoneImage;
        private BitmapImage speakerImage;


        /// Конструктор

        public MainPage()
        {
            InitializeComponent();

            // Таймер моделирует игровой цикл XNA Framework 
            // (микрофон взят из XNA Framework). Мы также используем этот таймер для мониторинга 
            // состояния воспроизведения аудио.
            DispatcherTimer dt = new DispatcherTimer();
            dt.Interval = TimeSpan.FromMilliseconds(33);
            dt.Tick += new EventHandler(dt_Tick);
            dt.Start();

            // Обработчик события для получения аудиоданных из буфера
            microphone.BufferReady += new EventHandler<EventArgs>(microphone_BufferReady);

            blankImage = new BitmapImage(new Uri("Images/blank.png", UriKind.RelativeOrAbsolute));
            microphoneImage = new BitmapImage(new Uri("Images/microphone.png", UriKind.RelativeOrAbsolute));
            speakerImage = new BitmapImage(new Uri("Images/speaker.png", UriKind.RelativeOrAbsolute));
        }

        /// Обновляет XNA FrameworkDispatcher и проверяет воспроизводится ли звук
        /// Если воспроизведение звука было остановлено, то это обновляет UI.

        void dt_Tick(object sender, EventArgs e)
        {
            try { FrameworkDispatcher.Update(); }
            catch { }

            if (true == soundIsPlaying)
            {
                if (soundInstance.State != SoundState.Playing)
                {
                    // Audio has finished playing
                    soundIsPlaying = false;

                    // Update the UI to reflect that the 
                    // sound has stopped playing
                    SetButtonStates(true, true, false);
                    UserHelp.Text = "Воспроизведение\nили запись";
                    StatusImage.Source = blankImage;
                }
            }
        }

        void microphone_BufferReady(object sender, EventArgs e)
        {
            // Получаем аудиоданные
            microphone.GetData(buffer);

            // Сохраняем аудиоданные в потоке
            stream.Write(buffer, 0, buffer.Length);
        }

        private void recordButton_Click(object sender, EventArgs e)
        {
            // Получение аудиоданных порциями по 1/2 секунды
            microphone.BufferDuration = TimeSpan.FromMilliseconds(500);

            // Выделяем память для хранения аудиоданных
            buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];

            stream.SetLength(0);

            // Начинаем запись
            microphone.Start();

            SetButtonStates(false, false, true);
            UserHelp.Text = "Запись";
            StatusImage.Source = microphoneImage;
        }

        private void stopButton_Click(object sender, EventArgs e)
        {
            if (microphone.State == MicrophoneState.Started)
            {
                microphone.Stop();
            }
            else if (soundInstance.State == SoundState.Playing)
            {
                soundInstance.Stop();
            }

            SetButtonStates(true, true, false);
            UserHelp.Text = "Готов";
            StatusImage.Source = blankImage;
        }

        private void playButton_Click(object sender, EventArgs e)
        {
            if (stream.Length > 0)
            {
                SetButtonStates(false, false, true);
                UserHelp.Text = "Воспроизведение";
                StatusImage.Source = speakerImage;

                // Воспроизводим аудио в новом потоке
                Thread soundThread = new Thread(new ThreadStart(playSound));
                soundThread.Start();
            }
        }

        private void playSound()
        {
            SoundEffect sound = new SoundEffect(stream.ToArray(), microphone.SampleRate, AudioChannels.Mono);
            soundInstance = sound.CreateInstance();
            soundIsPlaying = true;
            soundInstance.Play();
        }

        private void SetButtonStates(bool recordEnabled, bool playEnabled, bool stopEnabled)
        {
            (ApplicationBar.Buttons[0] as ApplicationBarIconButton).IsEnabled = recordEnabled;
            (ApplicationBar.Buttons[1] as ApplicationBarIconButton).IsEnabled = playEnabled;
            (ApplicationBar.Buttons[2] as ApplicationBarIconButton).IsEnabled = stopEnabled;
        }
    }
}
    

При нажатии на кнопку Запись начинается процесс записи.


После нажатия на кнопку Стоп можно или возобновить запись или перейти к воспроизведению.


Нажав на кнопку Воспроизведение можно прослушать запись.