使用音频图表,学习环境噪声和过滤在应用UWP

问题描述 投票:0回答:1

这是从这里扩展问题Using UWP monitor live audio and detect gun-fire/clap sound

由于Dernis我终于得到了代码工作监控实时音频和触发事件时,分贝数超过一定的范围内。

当我们在办公室运行/关闭/无声区这完美的作品。

但是,当我把应用开放之路,会有交通声音,风的声音,人们谈论的声音和其他的噪音和吹事件不能正确识别。

  • 我想实现像精益环境按钮。之前,应用程序启动监控,用户点击“精益环境”识别的灵敏度级,并设置过滤到我的现场音频,然后我开始监测打击。
  • 如果不加太多负荷,我想记录的音频文件。

就从哪里开始任何帮助,将不胜感激。

的OnNavigatedTo

protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
           //other logic
            await CreateInputDeviceNodeAsync(_deviceId);
        }

CreateInputDeviceNodeAsync

public async Task<bool> CreateInputDeviceNodeAsync(string deviceId)
        {
            Console.WriteLine("Creating AudioGraphs");
            // Create an AudioGraph with default settings
            AudioGraphSettings graphSettings = new AudioGraphSettings(AudioRenderCategory.Media)
            {
                EncodingProperties = new AudioEncodingProperties
                {
                    Subtype = "Float",
                    SampleRate = 48000,
                    ChannelCount = 2,
                    BitsPerSample = 32,
                    Bitrate = 3072000
                }
            };

            CreateAudioGraphResult audioGraphResult = await AudioGraph.CreateAsync(graphSettings);

            if (audioGraphResult.Status != AudioGraphCreationStatus.Success)
            {
                _rootPage.NotifyUser("Cannot create graph", NotifyType.ErrorMessage);
                return false;
            }

            _audioGraph = audioGraphResult.Graph;
            AudioGraphSettings audioGraphSettings =
                new AudioGraphSettings(AudioRenderCategory.GameChat)
                {
                    EncodingProperties = AudioEncodingProperties.CreatePcm(48000, 2, 32),
                    DesiredSamplesPerQuantum = 990,
                    QuantumSizeSelectionMode = QuantumSizeSelectionMode.ClosestToDesired
                };
            _frameOutputNode = _audioGraph.CreateFrameOutputNode(_audioGraph.EncodingProperties);
            _quantum = 0;
            _audioGraph.QuantumStarted += Graph_QuantumStarted;
            LoudNoise += BlowDetected;

            DeviceInformation selectedDevice = null;

            if (!string.IsNullOrWhiteSpace(_deviceId))
                selectedDevice = await DeviceInformation.CreateFromIdAsync(_deviceId);
            if (selectedDevice == null)
            {
                string device = Windows.Media.Devices.MediaDevice.GetDefaultAudioCaptureId(
                    Windows.Media.Devices.AudioDeviceRole.Default);
                if (!string.IsNullOrWhiteSpace(device))
                    selectedDevice = await DeviceInformation.CreateFromIdAsync(device);
                else
                {
                    _rootPage.NotifyUser($"Could not select Audio Device {device}", NotifyType.ErrorMessage);
                    return false;
                }
            }
            CreateAudioDeviceInputNodeResult result =
               await _audioGraph.CreateDeviceInputNodeAsync(MediaCategory.Media, audioGraphSettings.EncodingProperties,
                   selectedDevice);
            if (result.Status != AudioDeviceNodeCreationStatus.Success)
            {
                _rootPage.NotifyUser("Cannot create device output node", NotifyType.ErrorMessage);
                return false;
            }

            _selectedMicrophone = selectedDevice.Name;

            _deviceInputNode = result.DeviceInputNode;
            _deviceInputNode.AddOutgoingConnection(_frameOutputNode);
            _frameOutputNode.Start();
            _audioGraph.Start();
            return true;
        }

Graph_QuantumStarted

private void Graph_QuantumStarted(AudioGraph sender, object args)
        {
            if (++_quantum % 2 != 0) return;
            AudioFrame frame = _frameOutputNode.GetFrame();
            float[] dataInFloats;
            using (AudioBuffer buffer = frame.LockBuffer(AudioBufferAccessMode.Write))
            using (IMemoryBufferReference reference = buffer.CreateReference())
                unsafe
                {
                    // Get the buffer from the AudioFrame
                    // ReSharper disable once SuspiciousTypeConversion.Global
                    ((IMemoryBufferByteAccess) reference).GetBuffer(out byte* dataInBytes,
                        out var capacityInBytes);

                    var dataInFloat = (float*) dataInBytes;
                    dataInFloats = new float[capacityInBytes / sizeof(float)];

                    for (var i = 0; i < capacityInBytes / sizeof(float); i++)
                    {
                        dataInFloats[i] = dataInFloat[i];
                    }
                }

            double decibels = dataInFloats.Aggregate<float, double>(0f, (current, sample) => current + Math.Abs(sample));

            decibels = 20 * Math.Log10(decibels / dataInFloats.Length);
            _decibelList.Add(decibels);

            if (double.IsInfinity(decibels) || decibels < _threshold) return;//-45
            if (_watch != null && _watch.Elapsed <= TimeSpan.FromSeconds(1)) return;
            LoudNoise?.Invoke(this, decibels);
            _watch = Stopwatch.StartNew();
        }
c# audio uwp audio-recording
1个回答
1
投票

这仅仅是统计数字。你要真正有它的功能(也许让用户通过保持和释放按钮决定)可能之前收集的数据的至少50帧(1秒)。然后,你可能会想,以确定的分贝数通常在。我能想到的3种方法可以做到这一点。

private void Graph_QuantumStarted(AudioGraph sender, object args)
        {
            ...
            double decibels = dataInFloats.Aggregate<float, double>(0f, (current, sample) => current + Math.Abs(sample)); // I dislike the fact that the decibels variable is initially inaccurate, but it's your codebase.
            decibels = 20 * Math.Log10(decibels / dataInFloats.Length);


            if (scanning) // class variable (bool), you can set it from the UI thread like this
            {
                _decibelList.Add(decibels); // I assume you made this a class variable
            }
            else if (decibels == Double.NaN)
            {
                // Code by case below
            }
            else if (decibels > _sensitivity) //_sensitivity is a class variable(double), initialized to Double.NaN
            {
                LoudNoise?.Invoke(this, true); // Calling events is a wee bit expensive, you probably want to handle the sensitivity before Invoking it, I'm also going to do it like that to make this demo simpler
            }
        }
  1. 如果你能控制确保没有秒杀够响亮你希望它熄灭你可以采取所有这些帧的最大价值,并说,如果这是在灵敏度maxDecibels + Math.Abs(maxDecibels* 0.2)(分贝可能是负的,因此ABS)。
double maxDecibels = _decibelList.OrderByDescending(x => x)[0];
_sensitivity = maxDecibels + Math.Abs(maxDecibels* 0.2);
  1. 如果当有一个秒杀你无法控制,那么你可以收集这些帧,排序,并把它取(你的100项清单)项目[24],并说这是灵敏度。
sensitivity = _decibelList.OrderByDescending(x => x)[24]; // If you do a variable time you can just take Count/4 - 1 as the index
  1. (我认为这是最好的,但我真的不知道统计)走帧的分贝的列表,并跟踪值的平均差异和什么指标最改变了它。随后,从该指数后发现最大值,说变化的75%〜还有就是敏感性试验。 (不要使用这一个LinkedList)
int greatestChange, changeIndex = 0;
double p = Double.NaN; // Previous
for (int i = 0; i < _decibelList.Count(); i++)
{
    if (p != Double.Nan)
    {
        change = Math.Abs(_decibelList[i] - p);
        if (Math.Abs(change > greatestChange)
        {
            greatestChange = change;
            changeIndex = i;
        } 
    }
    p = _decibelList[i];
}

int i = changeIndex;
p = Double.NaN; // reused
double c= Double.NaN; // Current
do
{
    p = c != Double.NaN ? c : _decibelList[i];
    c = _decibelList[++i];
} while (c < p);

_sensitivity = ((3 * c) + _decibelList[changeIndex]) / 4;

Note: You can (kind of) remove the need to sort by having a LinkedList and inserting in the appropiate place

© www.soinside.com 2019 - 2024. All rights reserved.