Форум программистов, компьютерный форум, киберфорум
Программирование звука
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
 Аватар для Donet
23 / 23 / 3
Регистрация: 19.11.2013
Сообщений: 74

DirectSound C#. Как считать ровно минуту с микрофона?

08.05.2015, 08:25. Показов 2652. Ответов 7

Студворк — интернет-сервис помощи студентам
Вот сколько ищу не могу найти. Как считать ровно минуту с микрофона при использовании DirectSound.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
        class Microfon
        {
            CaptureBuffer captureBuffer;
            WaveFormat waveFormat;
            CaptureBufferDescription captureBufferDescription;
            Capture capture;
            DeviceInformation deviceInformation = new DeviceInformation();
            public Array array;
 
            public Microfon(DeviceInformation deviceInformation)
            {
                waveFormat.SamplesPerSecond = 44100;
                waveFormat.BitsPerSample = 16;
                waveFormat.Channels = 2;
                waveFormat.FormatTag = WaveFormatTag.Pcm;
                waveFormat.BlockAlign = (short)(waveFormat.Channels * (waveFormat.BitsPerSample / 8));
                waveFormat.AverageBytesPerSecond = waveFormat.SamplesPerSecond * waveFormat.BlockAlign;
                captureBufferDescription.BufferBytes = waveFormat.AverageBytesPerSecond;
                captureBufferDescription.Format = waveFormat;
                capture = new Capture(deviceInformation.DriverGuid);
                captureBuffer = new CaptureBuffer(captureBufferDescription, capture);
            }
            public void read(){
                int offset = 0;
                captureBuffer.Start(true);
                Thread.Sleep(1000);
                array = captureBuffer.Read(offset, typeof(byte), LockFlag.FromWriteCursor, captureBuffer.Caps.BufferBytes);
                captureBuffer.Stop();
            }
        }
Проблема вот в этой части кода.

C#
1
2
3
4
5
6
7
            public void read(){
                int offset = 0;
                captureBuffer.Start(true);
                Thread.Sleep(1000);
                array = captureBuffer.Read(offset, typeof(byte), LockFlag.FromWriteCursor, captureBuffer.Caps.BufferBytes);
                captureBuffer.Stop();
            }
И подскажите пожалуйста как запустить считывания данных с двух mic входов в один такт.
Зараз я это сделал вот так.

C#
1
2
3
4
5
6
7
mic1 = new Microfon(captureDevicesCollection[comboBox1.SelectedIndex]);
mic2 = new Microfon(captureDevicesCollection[comboBox2.SelectedIndex]);                     
Thread sound1 = new Thread(delegate() { mic1.read(); });
Thread sound2 = new Thread(delegate() { mic2.read(); });
sound1.Start();
sound2.Start();
Thread.Sleep(2000);
Но между микрофонами задержка в 200 - 600 тактов с 44100. Это не процессорный такт, такт звуковой карти карты.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.05.2015, 08:25
Ответы с готовыми решениями:

DateTime: считать секунду за минуту
DateTime d = DateTime.Now; label1.Text = d.Minute.ToString(); // А КАК МНЕ ВЗЯТЬ ВРЕМЯ КОТОРОЕ (НАПРИМЕН СЕЙЧАС 1.49 А КОГДА БУДЕТ...

Требуется "считать" громкость шума с микрофона как некое число
Требуется "считать" громкость шума с микрофона как некое число, характеризующее уровень шума. Не знаю, как это сделать. Подскажите,...

Считать файл и вывести число событий NOK за каждую минуту
Здравствуйте. Помогите пожалуйста разобраться. Первый раз на форуме пишу, до этого как то справлялся, сейчас уже 2 день сижу над...

7
 Аватар для Patagolik
6 / 5 / 2
Регистрация: 12.04.2015
Сообщений: 35
09.05.2015, 14:31
Секунду проще всего посчитать по количеству записанных семплов:
bytesInSecond = waveFormat.SamplesPerSecond * (waveFormat.BitsPerSample / 8) * waveFormat.Channels * 60;
Т.е. Записать чуть больше, а потом обрезать.

Thread.Sleep(1000); - всегда больше секунды.

Что касается одновременной записи, то тут все сложнее. Если каналы на одной звуковой карте, то может так случиться, что это физически невозможно.

Но ту задержку которую вы видите, вы получаете не из-за тактов звуковой карты, а из-за того что на создание потока нужно время.

Его можно минимизировать если сначала создать два потока, заморозить их при помощи мютексов, например, а потом из управляющего потока запустить их по очереди. Так задержка должна быть меньше.

А еще меньше задержку можно сделать примерно так (в учебниках учат так не делать, и какие-нибудь решарперы на это должны ругаться):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mic1 = new Microfon(captureDevicesCollection[comboBox1.SelectedIndex]);
mic2 = new Microfon(captureDevicesCollection[comboBox2.SelectedIndex]);                     
 
bool flag true;
 
Thread sound1 = new Thread(delegate() { while (flag); mic1.read(); });
Thread sound2 = new Thread(delegate() { while (flag); mic2.read(); });
sound1.Start();
sound2.Start();
 
Thread.Sleep(1000);
 
flag = false;
 
Thread.Sleep(2000);
1
 Аватар для Donet
23 / 23 / 3
Регистрация: 19.11.2013
Сообщений: 74
09.05.2015, 18:13  [ТС]
Спасибо за ответ. Да это действительно даст нам задержку намного меньше но мне нужно чтобы задержек совсем не было. Думал привинтить к каждому значению время. Но не знаю к чему цеплять эту дату. Цепляю к старту записи не подходит, к концу записи тоже не подходит, а значения записываются в буфере на звуковой и после записи секунды перемещаются к нам в масив. Что не даёт нам прикрепить реального времени.
0
 Аватар для Donet
23 / 23 / 3
Регистрация: 19.11.2013
Сообщений: 74
09.05.2015, 18:25  [ТС]
Вот как выглядит всё это время кажет что задержек нет, а график говорит о другом.

Время узнаю. вод так.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Microfon
        {
            CaptureBuffer captureBuffer;
            WaveFormat waveFormat;
            CaptureBufferDescription captureBufferDescription;
            Capture capture;
            DeviceInformation deviceInformation = new DeviceInformation();
            public Array array;
            public long time;
            public Microfon(DeviceInformation deviceInformation)
            {
                waveFormat.SamplesPerSecond = 44100;
                waveFormat.BitsPerSample = 16;
                waveFormat.Channels = 2;
                waveFormat.FormatTag = WaveFormatTag.Pcm;
                waveFormat.BlockAlign = (short)(waveFormat.Channels * (waveFormat.BitsPerSample / 8));
                waveFormat.AverageBytesPerSecond = waveFormat.SamplesPerSecond * waveFormat.BlockAlign;
                captureBufferDescription.BufferBytes = waveFormat.AverageBytesPerSecond;
                captureBufferDescription.Format = waveFormat;
                capture = new Capture(deviceInformation.DriverGuid);
                captureBuffer = new CaptureBuffer(captureBufferDescription, capture);
                
            }
            public void read(){
                int offset = 0;
                captureBuffer.Start(true);
                time = DateTime.UtcNow.Ticks;
                Thread.Sleep(1000);
                array = captureBuffer.Read(offset, typeof(byte), LockFlag.FromWriteCursor, captureBuffer.Caps.BufferBytes);
                captureBuffer.Stop();
            }
        }
C#
1
2
3
4
5
6
7
8
9
10
            mic1 = new Microfon(captureDevicesCollection[comboBox1.SelectedIndex]);
            mic2 = new Microfon(captureDevicesCollection[comboBox2.SelectedIndex]);                     
            Thread sound1 = new Thread(delegate() { mic1.read(); });
            Thread sound2 = new Thread(delegate() { mic2.read(); });
            sound1.Start();
            sound2.Start();
            Thread.Sleep(1000);
            label1.Text = ((mic1.time - mic2.time)).ToString();
            label2.Text = mic1.time.ToString();
            label3.Text = mic2.time.ToString();
0
 Аватар для Donet
23 / 23 / 3
Регистрация: 19.11.2013
Сообщений: 74
09.05.2015, 18:54  [ТС]
Вот как это выглядит на двух звуковых картах.
0
 Аватар для Patagolik
6 / 5 / 2
Регистрация: 12.04.2015
Сообщений: 35
09.05.2015, 19:48
Виндовс вообще не является реалтаймовой операционной системой. Т.ч. то что вы от него хотите, грубо говоря, невозможно. Но возможно можно добиться какого-нибудь компромисса.

Мне не понятно как вы определяете точку с которой нужно рисовать кривую. Или вы читаете буфер, а в нем звук начинается не с начала? И что вы называете тактом?

И еще пара замечаний.

DateTime.UtcNow.Ticks; - не самый быстрый метод (он там внутри создает объект DateTime и это само по себе тормозно и не точно). Лучше вызывать Environment.TickCount (он просто дергает метод АПИ), главное помнить что значение может быть отрицательным.
Во вторых, АПИштый GetTickCount() хоть и есть самый точный метод, но тоже недостаточно точный для работы со звуком и видео. Его точность ограничивается точностью системного таймера, а он тикает примерно 4 раза в секунду (всего лишь).

Т.ч. верить всем этим значениям в контексте звука бессмысленно.

----------------------------

И на сколько уменьшилось расхождение если запускать потоки чтения одновременно по одному флагу?
1
 Аватар для Donet
23 / 23 / 3
Регистрация: 19.11.2013
Сообщений: 74
12.05.2015, 12:07  [ТС]
Я рисую кривую вот так.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
            Byte[] abuffer = new byte[mic1.array.Length];
            Array.Copy(mic1.array, abuffer, mic1.array.Length);
            Byte[] bbuffer = new byte[mic2.array.Length];
            Array.Copy(mic2.array, bbuffer, mic2.array.Length);
            chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
            chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
            chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
            chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true;
            int n = 0;
            for (int i = 0; i < 2000; i++)
            {
 
                chart1.Series[0].Points.AddXY(i, (short)((abuffer[n + 1] << 8) | abuffer[n + 0]));
                chart1.Series[1].Points.AddXY(i, (short)((abuffer[n + 3] << 8) | abuffer[n + 2]));
                chart1.Series[2].Points.AddXY(i, (short)((bbuffer[n + 1] << 8) | bbuffer[n + 0]));
                chart1.Series[3].Points.AddXY(i, (short)((bbuffer[n + 3] << 8) | bbuffer[n + 2]));
                n += 4;
            }
Под тактом я имею ввиду количество считанных данных в секунду.

C#
1
waveFormat.SamplesPerSecond = 44100;
0
 Аватар для Patagolik
6 / 5 / 2
Регистрация: 12.04.2015
Сообщений: 35
12.05.2015, 19:26
Ну тогда вы действительно хотите слишком многого.

Мне тут подумалось, что смещение может быть вызвано самим АЦП в звуковой карте. Просто АЦП это штука не мгновенная и работает с задержкой. Более того на разных картах АЦП могут быть разными и задержки у них тоже могут быть разными, не говоря уже про остальную реализацию.

Мастерите программную настраиваемую задержку для синхронизации, если это так важно.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.05.2015, 19:26
Помогаю со студенческими работами здесь

Переменная выдает 1 минуту одну картинку 2 минуту другую
Здравствуйте, подскажите php код, нужно что бы перейдя по странице открывалась 1 картинка, а если зайти через минуту на эту же страницу то...

Как задействовать DirectSound?
В DirectX9 SDK June 2010 не могу задействовать DirectSound какие хейдеры нухно включить в проект?

Как правильно подключить Microsoft.DirectX.DirectSound
Пишу что то на подобие голосового чата, пытаюсь захватить звук с микрофона. Нашел в интернете пример работы со звуком с помощью using...

DirectSound. Как правильно, и какую библиотеку следует добавить?
Ребята, нужна ваша помощь. MVS 2010 выдаёт следующее 1&gt;DXUTsound.obj : error LNK2019: unresolved external symbol __imp__mmioClose@8...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru