Название: Проблема применения кольцевого буфера Отправлено: Miralissa от Январь 04, 2020, 13:12 Ребята, help! Хочу лёгкий аудио-рекордер на Qt + PortAudio, застряла на тестах передачи данных через кольцевой буфер. Цепочка представляет собой следующий маршрут: PortAudio -> Callback-функция(принимающая буферы с сэмплами) -> Кольцевой буфер -> обработчик (анализ и преобразование сэмплов/запись в файл) -> функция-индикатор (передаёт пиковые значения на QProgressBar). Загвоздка происходит при попытке записать данные в кольцевой буфер, выдаёт Exception at 0x7ff69bf44d73, code: 0xc0000005: read access violation at: 0xa, flags=0x0 (first chance). Не могу понять где я накосячила ^_^, вроде по указателям всё сходится... Чувствую себя жутко тупой... ниже привожу код:
Это мой кольцевой буффер: Код: #include <QObject> Это обработчик, который должен запускаться в отдельном потоке: DSPEngine.h Код: #include <QObject> DSPEngine.cpp Код: #include "dspengine.h" И основной модуль: BlackBox.h Код: #include <QMainWindow> BlackBox.cpp Код: #include "blackbox.h" Название: Re: Проблема применения кольцевого буфера Отправлено: Авварон от Январь 04, 2020, 15:14 Точно падает тут? Может, падает
Код: rptr[i] Код: void addSample(T sample) //ЗДЕСЬ ВОЗНИКАЕТ ОШИБКА ЧТЕНИЯ ПАМЯТИ Вообще это странный код, head увеличивается дважды. Можно же проще: Код: void addSample(T sample) //ЗДЕСЬ ВОЗНИКАЕТ ОШИБКА ЧТЕНИЯ ПАМЯТИ Название: Re: Проблема применения кольцевого буфера Отправлено: Miralissa от Январь 04, 2020, 16:00 Точно падает тут? Может, падает Код: rptr[i] Попробовала поменять на *rptr++, ошибка сместилась сюда (но ведь это не должно влиять - к членам массива в цикле вроде бы можно обращаться и так ptr и так *ptr++) ???: Код: void addSample(T sample) Вообще это странный код, head увеличивается дважды. Можно же проще: Код: void addSample(T sample) Посчитала, что % будет дороже условия, возможно я ошибалась :) Название: Re: Проблема применения кольцевого буфера Отправлено: Miralissa от Январь 05, 2020, 01:01 Так, кольцевой буфер я проверила в VS - работает как часы 8), внесла пару поправок. Возможно, стоит попробовать запустить цепочку не применяя потоки QThread. У меня почему-то он всегда капризничает. ::)
Название: Re: Проблема применения кольцевого буфера Отправлено: Авварон от Январь 05, 2020, 12:32 Откуда вообще информация, что в rptr есть bufferLength элементов?
Название: Re: Проблема применения кольцевого буфера Отправлено: Miralissa от Январь 05, 2020, 13:46 Откуда вообще информация, что в rptr есть bufferLength элементов? Callback-функция периодически вызывается библиотекой PortAudio для передачи заполненного на величину bufferLength буфера после вызова метода Pa_StartStream() в файле BlackBox.cpp, и когда я включала qDebug в цикл Код: for (int i = 0; i < bufferLength; i++) Название: Re: Проблема применения кольцевого буфера Отправлено: Igors от Январь 05, 2020, 15:54 Так, кольцевой буфер я проверила в VS - работает как часы 8), внесла пару поправок. Ну VS не такой уж авторитет :) И "парой поправок" там не отделаться, я бы сделал такКод Писал здесь, возможны ошибки Посчитала, что % будет дороже условия, возможно я ошибалась :) Оптимизировать можно/нужно когда достигнут ф-ционвлEdit: чуть подправил Название: Re: Проблема применения кольцевого буфера Отправлено: qate от Январь 06, 2020, 00:28 Есть же сигналы и слоты с безопасной передачей данных между потоками, но нет - будем городить кольцевые буфера !
Название: Re: Проблема применения кольцевого буфера Отправлено: Igors от Январь 06, 2020, 14:19 Есть же сигналы и слоты с безопасной передачей данных между потоками, но нет - будем городить кольцевые буфера ! Идет (бесконечный) поток данных, требуется хранить N последних. Как это сделать сигналами/слотами? Название: Re: Проблема применения кольцевого буфера Отправлено: qate от Январь 06, 2020, 17:35 Идет (бесконечный) поток данных, требуется хранить N последних. Как это сделать сигналами/слотами? 1. сигналом выдать данные из callback от устройства в поток обработки, тем самым обеспечить потокобезопасность 2. в потоке обработке уже можно что угодно делать, возможно у ТС проблема с потоками, весь код тайна и не показан Название: Re: Проблема применения кольцевого буфера Отправлено: Miralissa от Январь 06, 2020, 21:51 Есть же сигналы и слоты с безопасной передачей данных между потоками, но нет - будем городить кольцевые буфера ! Вот приходила же в голову такая идея, сигналом передавать ссылку на массив полученный в callback-функции и спокойно работать в другом потоке!! Надо попробовать! ;) А кольцевые буфера ::) городила, потому что воспринимала это как единственную возможность подружить асинхронные процессы. Драйвер аудиокарты может наполнять буфер с разной скоростью (хотя в "вакууме" скорость потока данных, создаваемого АЦП должна быть однородна и соответствовать частоте дискретизации). Далее я планировала анализ значений сэмплов (задача - писать только когда есть звук выше определённого порога), конверсию в формат аас со сжатием и запись в файл. То есть обработка данных может занять больше времени, чем их получение. Ну а в тройном кольцевом буфере места для записи достаточно, чтобы записать 2 буфера от драйвера, пока читается 1 уже записанный, конвертируется и пишется в файл. Спасибо за совет, я обязательно попробую собрать вариант на сигналах-слотах и напишу о результатах! :-* Название: Re: Проблема применения кольцевого буфера Отправлено: Igors от Январь 07, 2020, 14:49 1. сигналом выдать данные из callback от устройства в поток обработки, тем самым обеспечить потокобезопасность Ну обработчик будет получать фрагмент за фрагментом, все равно их придется как-то склеивать, отсекать старые и.т.д. Все равно маячит тот же кольцевой буфер, пусть на стороне обработчика2. в потоке обработке уже можно что угодно делать, А кольцевые буфера ::) городила, потому что воспринимала это как единственную возможность подружить асинхронные процессы. "В огороде бузина, в Киеве дядька". т.е. эти вещи никак не связаны. Далее я планировала анализ значений сэмплов (задача - писать только когда есть звук выше определённого порога) И что, появился адын сампл выше порога - погнали писать? Это может быть случайный выброс/выхлоп. Скорее всего (ну это я предполагаю) надо поймать момент "сигнал пошел", напр среднее N самплов превысило порог. Поэтому для начала пихать все в кольцевой буфер (в нитке АЦП) - вполне здравая мысль. А когда сигнал пойман - отсылать обработчику, как сказал товарищ.Название: Re: Проблема применения кольцевого буфера Отправлено: qate от Январь 08, 2020, 00:02 Ну обработчик будет получать фрагмент за фрагментом, все равно их придется как-то склеивать, отсекать старые и.т.д. Все равно маячит тот же кольцевой буфер, пусть на стороне обработчика мне всеже не ясно - зачем отсекать старые ? звуковые редакторы пишут звук весь - от нажатия на "rec" до нажатия на "stop" писать буфера на стороне обработчика лучше тем, что отвязываемся от потока записи, он не должен занять про буфера обработки если сигнал на каждый байт посылать не желательно - можно и накопить немного в обычном массиве, хотя не думаю, что такое будет при записи 44 кГц / 16 бит Название: Re: Проблема применения кольцевого буфера Отправлено: Miralissa от Январь 10, 2020, 01:38 Спасибо всем за помощь, основной механизм программы работает!! ;) В очередной раз убедилась, что между потоками QThread не должно быть ничего кроме сигналов-слотов, ошибка была в том что обращения к кольцевому буферу происходили в трёх разных потоках через указатели. Теперь кольцевой буфер я перенесла в поток обработчика, он действительно нужен, так как данные могут не успеть сконвертироваться и записаться в файл до получения новой порции сэмплов. Т.е., callback получает данные от драйвера и передаёт их по указателю сигналом в поток обработки, где они записываются в кольцевой буфер и если есть флаг готовности обработчика, считываются уже из буфера.
|