Kinect 开发 —— 录音

不涉及语音识别~~


<Window x:Class="KinectRecordAudio.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Audio Recorder" Height="226" Width="405">
    <Grid Width="369" Height="170">
        <Button Content="Play" Height="44" HorizontalAlignment="Left" Margin="12,13,0,0" Name="button1" VerticalAlignment="Top" Width="114" Click="button1_Click"  IsEnabled="{Binding IsPlayingEnabled}" FontSize="18"></Button>
        <Button Content="Record" Height="44" HorizontalAlignment="Left" Margin="132,13,0,0" Name="button2" VerticalAlignment="Top" Width="110" Click="button2_Click"  IsEnabled="{Binding IsRecordingEnabled}" FontSize="18"/>
        <Button Content="Stop" Height="44" HorizontalAlignment="Left" Margin="248,13,0,0" Name="button3" VerticalAlignment="Top" Width="107" Click="button3_Click"  IsEnabled="{Binding IsStopEnabled}" FontSize="18"/>
        <CheckBox Content="Noise Suppression" Height="16" HorizontalAlignment="Left" Margin="16,77,0,0"  VerticalAlignment="Top" Width="142" IsChecked="{Binding IsNoiseSuppressionOn}" />
        <CheckBox Content="Automatic Gain Control" Height="16" HorizontalAlignment="Left" Margin="16,104,0,0"  VerticalAlignment="Top"  IsChecked="{Binding IsAutomaticGainOn}"/>
        <CheckBox Content="AEC" Height="44" HorizontalAlignment="Left" IsChecked="{Binding IsAECOn}" Margin="16,129,0,0"  VerticalAlignment="Top" />
    </Grid>
</Window>

 


namespace KinectRecordAudio
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        // INotifyPropertyChanged 接口用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知。

        string _recordingFileName;  // 录音文件名
        MediaPlayer _mplayer;
        bool _isPlaying;
        bool _isNoiseSuppressionOn;
        bool _isAutomaticGainOn;
        bool _isAECOn;

            // IsEnabled="{Binding IsRecordingEnabled}" 将控件与方法绑定

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += delegate { KinectSensor.KinectSensors[0].Start(); };
            _mplayer = new MediaPlayer();
            _mplayer.MediaEnded += delegate { _mplayer.Close(); IsPlaying = false; };
            this.DataContext = this;
        }

        private void Play()
        {
            IsPlaying = true;
            _mplayer.Open(new Uri(_recordingFileName, UriKind.Relative));
            _mplayer.Play();
        }

        private void Record()
        {
            Thread thread = new Thread(new ThreadStart(RecordKinectAudio));
            thread.Priority = ThreadPriority.Highest;   // 线程优先级
            thread.Start();
        }

        private void Stop()
        {
            KinectSensor.KinectSensors[0].AudioSource.Stop();
            IsRecording = false;
        }
        private object lockObj = new object();

        private void RecordKinectAudio()
        {
            lock (lockObj)
            {
                    // 线程加锁
                IsRecording = true;

                var source = CreateAudioSource();

                var time = DateTime.Now.ToString("hhmmss");
                _recordingFileName = time + ".wav";
                using (var fileStream =
                new FileStream(_recordingFileName, FileMode.Create))
                {
                    RecorderHelper.WriteWavFile(source, fileStream);
                }

                IsRecording = false;
            }

        }

        private KinectAudioSource CreateAudioSource()
        {
            var source = KinectSensor.KinectSensors[0].AudioSource;
            source.BeamAngleMode = BeamAngleMode.Adaptive;
            source.NoiseSuppression = _isNoiseSuppressionOn;
            source.AutomaticGainControlEnabled = _isAutomaticGainOn;

            if (IsAECOn)
            {
                source.EchoCancellationMode = EchoCancellationMode.CancellationOnly;
                source.AutomaticGainControlEnabled = false;
                IsAutomaticGainOn = false;
                source.EchoCancellationSpeakerIndex = 0;
            }

            return source;  // 返回经过处理的数据源
        }

        #region user interaction handlers

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            Play();
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            Record();
        }

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            Stop();
        }

        #endregion

        #region properties

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        private bool IsPlaying
        {
            get
            {
                return _isPlaying;
            }
            set
            {
                if (_isPlaying != value)
                {
                    _isPlaying = value;
                    OnPropertyChanged("IsRecordingEnabled");
                }
            }
        }

        private bool IsRecording
        {
            get
            {
                return RecorderHelper.IsRecording;
            }
            set
            {
                if (RecorderHelper.IsRecording != value)
                {
                    RecorderHelper.IsRecording = value;
                    OnPropertyChanged("IsPlayingEnabled");
                    OnPropertyChanged("IsRecordingEnabled");
                    OnPropertyChanged("IsStopEnabled");
                }
            }
        }
        public bool IsPlayingEnabled
        {
            get { return !IsRecording; }
        }

        public bool IsRecordingEnabled
        {
            get { return !IsPlaying && !IsRecording; }
        }

        public bool IsStopEnabled
        {
            get { return IsRecording; }
        }

        public bool IsNoiseSuppressionOn
        {
            get
            {
                return _isNoiseSuppressionOn;
            }
            set
            {
                if (_isNoiseSuppressionOn != value)
                {
                    _isNoiseSuppressionOn = value;
                    OnPropertyChanged("IsNoiseSuppressionOn");
                }
            }
        }

        public bool IsAutomaticGainOn
        {
            get
            {
                return _isAutomaticGainOn;
            }
            set
            {
                if (_isAutomaticGainOn != value)
                {
                    _isAutomaticGainOn = value;
                    OnPropertyChanged("IsAutomaticGainOn");
                }
            }
        }

        public bool IsAECOn
        {
            get
            {
                return _isAECOn;
            }
            set
            {
                if (_isAECOn != value)
                {
                    _isAECOn = value;
                    OnPropertyChanged("IsAECOn");
                }
            }
        }

        #endregion
    }
}

 


class RecorderHelper
{
    static byte[] buffer = new byte[4096];
    static bool _isRecording;

    public static bool IsRecording
    {
        get
        {
            return _isRecording;
        }
        set
        {
            _isRecording = value;
        }
    }

    public static void WriteWavFile(KinectAudioSource source, FileStream fileStream)
    {
        var size = 0;
        //write wav header placeholder
        WriteWavHeader(fileStream, size);   // size=0;
        using (var audioStream = source.Start())
        {
            // Starts capturing audio from the device. The data can be read using the returned stream.
            //chunk audio stream to file
            while (audioStream.Read(buffer, 0, buffer.Length) > 0 && _isRecording)
            {
                fileStream.Write(buffer, 0, buffer.Length);
                size += buffer.Length;

            }
        }

        //write real wav header
        // 方法开始写入一个假的头文件,然后读取Kinect中的音频数据流,然后填充FileStream对象,直到_isRecoding属性被设置为false。然后检查已经写入到文件中的数据流大小,用这个值来改写之前写入的文件头
        long prePosition = fileStream.Position;
        fileStream.Seek(0, SeekOrigin.Begin);
        WriteWavHeader(fileStream, size);   // size = file length
        fileStream.Seek(prePosition, SeekOrigin.Begin);
        fileStream.Flush();
    }

    public static void WriteWavHeader(Stream stream, int dataLength)
    {
        using (MemoryStream memStream = new MemoryStream(64))
        {
            // 基于指定的字节数组初始化 MemoryStream 类的无法调整大小的新实例

            int cbFormat = 18;
            WAVEFORMATEX format = new WAVEFORMATEX()
            {
                wFormatTag = 1,
                nChannels = 1,
                nSamplesPerSec = 16000,
                nAvgBytesPerSec = 32000,
                nBlockAlign = 2,
                wBitsPerSample = 16,
                cbSize = 0
            };

            using (var bw = new BinaryWriter(memStream))
            {

                WriteString(memStream, "RIFF");
                bw.Write(dataLength + cbFormat + 4);
                WriteString(memStream, "WAVE");
                WriteString(memStream, "fmt ");
                bw.Write(cbFormat);

                bw.Write(format.wFormatTag);
                bw.Write(format.nChannels);
                bw.Write(format.nSamplesPerSec);
                bw.Write(format.nAvgBytesPerSec);
                bw.Write(format.nBlockAlign);
                bw.Write(format.wBitsPerSample);
                bw.Write(format.cbSize);

                WriteString(memStream, "data");
                bw.Write(dataLength);

                memStream.WriteTo(stream);
            }
        }
    }

    static void WriteString(Stream stream, string s)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(s);
        stream.Write(bytes, 0, bytes.Length);
    }

    struct WAVEFORMATEX
    {
        public ushort wFormatTag;
        public ushort nChannels;
        public uint nSamplesPerSec;
        public uint nAvgBytesPerSec;
        public ushort nBlockAlign;
        public ushort wBitsPerSample;
        public ushort cbSize;
    }
}

C#不支持直接写wma文件,需要C++的 WAVEFORMATEX 结构体

Kinect 开发 —— 录音

时间: 2024-11-13 06:34:48

Kinect 开发 —— 录音的相关文章

Kinect 开发 &mdash;&mdash; 开发前的准备工作

Kinect SDK v1.5 支持托管语言和非托管语言 Xbox360的游戏是基于Xbox360开发工具包 (XDK)开发的,Xbox 360和Windows是两个完全不同的系统架构.使用Kinect for windows SDK 编译的代码并不能直接部署到Xbox环境中 Kinect 应用程序必须在一个原生操作系统环境下编译,运行 -- 无法在虚拟机上运行 Kinect 开发 —— 开发前的准备工作,布布扣,bubuko.com

Kinect 开发 &mdash;&mdash; 用户交互设计的若干思考

Metro 风格 windows 8 Kinect Hub 手势原型设计 悬停选择     翻页控制 关节点重叠的处理方法 将箭靶设置在画面的边缘,这样玩家持弓的角度与屏幕保持一个大约45度的锐角,这样Kinect可以很精确的检测到拉弓射箭的动作 手势天生具有一定随意性,而且具有一定的文化背景差异性   手与设备的非接触性 虚拟触摸的界面 Kinect 使交互"柔软化"   确认操作保持简单一致 悬停选择 -- 将手停在想要选择的项目方块或按钮上,等待进度圆圈的填充,这个过程会在T时间

【Kinect开发笔记之(一)】初识Kinect

一.Kinect简介 Kinect是微软在2010年6月14日对XBOX360体感周边外设正式发布的名字.它是一种3D体感摄影机(开发代号"Project Natal"),同时它导入了即时动态捕捉.影像辨识.麦克风输入.语音辨识.社群互动等功能. 二.Kinect分类 Kinect for Xbox 360:该版本设计之初就是为了Xbox 360定制的,并未考虑其他的平台.从微软授权角度而言,它无法用于商业开发. Kinect for Windows : 固件上做了升级,支持"

【Kinect开发笔记之(二)】Kinect for windows发展历程

新版本SDK和旧版本的SDK完全兼容,如果您之前安装过旧版本的,可以直接安装新版本的SDK,但是如果您之前的开发版本是Beta版的,则需要卸载之后再安装新版本.在Kinect for Windows SDK 1.0版本中,SDK和示例文件是打包一起安装的.而在之后的版本,为了可以分别升级,微软把这两者分开独立为Kinect for Windows SDK和Kinect for Windows Developer Toolkit这两部分,所以需要分别下载安装, Kinect for Windows

Kinect 开发 &mdash;&mdash; 骨骼数据与彩色影像和深度影像的对齐

在显示彩色影像和深度影像时最好使用WriteableBitmap对象: 要想将骨骼数据影像和深度影像,或者彩色影像叠加到一起,首先要确定深度影像的分辨率和大小,为了方便,这里将深度影像数据和彩色影像数据都采用640x480Fps30的格式,同时将Grid的大小也设置为640*480. 要将骨骼数据和深度影像数据叠加,需要将关节点转换到深度影像所在空间中,可以直接调用MapSkeletonPointToDepthPoint,如果要将骨骼数据叠加到彩色影像上,只需要调用MapSkeletonPoin

Kinect 开发 &mdash;&mdash; 语音识别(下)

使用定向麦克风进行波束追踪 (Beam Tracking for a Directional Microphone) 可以使用这4个麦克风来模拟定向麦克风产生的效果,这个过程称之为波束追踪(beam tracking) 界面上的细长矩形用来指示某一时刻探测到的说话者的语音方向.矩形有一个旋转变换,在垂直轴上左右摆动,以表示声音的不同来源方向. <Rectangle Fill="#1BA78B" HorizontalAlignment="Left" Margin

Kinect 开发 &mdash;&mdash; 姿势识别

姿势和手势通常会混淆,但是他们是两个不同的概念.当一个人摆一个姿势时,他会保持身体的位置和样子一段时间.但是手势包含有动作,例如用户通过手势在触摸屏上,放大图片等操作. 通常,游戏者很容易模仿指定姿势并且比较容易编写算法来识别指定的姿势.例如,如果开发一个用户在天上飞的游戏. 一种控制游戏的方式是,游戏者像鸟一样挥动手臂.挥动的频率越快游戏角色飞的越快,这是一个手势.还有一种方法是,展开双臂,双臂张得越快开,飞的越快.双臂离身体越近,飞的越慢. 身体以及各个关节点的位置定义了一个姿势.更具体的来

Kinect开发资源汇总

Kinect开发资源汇总   转自: http://www.sigvc.org/bbs/forum.php?mod=viewthread&tid=254&highlight=kinect By doctorimage整理 开发Kinect应用本质上和开发其他Windows应用一样,不同的是该SDK支持Kinect感应器的相关功能,比如彩色图像.深度图像.音频.骨骼动画数据等. 本文整理了Kinect应用开发的相关资源,如果你正在进行Kinect开发或打算进行Kinect开发,这将对你有很大

Kinect 开发 &mdash;&mdash; 引言

自然人机交互设计技术 (全息三维投影,手势肢体识别,眼动跟踪 ...) 符合人类心理的交互方式 自然用户界面 -- Natural User Interface 有机用户界面 -- Organic User Interface   第六感设备 -- 手势识别,摄像头,投影,云计算 通过对熟知的技术的组合,产生一种NB 的应用               http://www.pranavmistry.com/ 追影技术 -- 用普通摄像头结合运动跟踪算法,实现体感 微软的 CamBot 技术,G