Russian Qt Forum
Ноябрь 26, 2024, 08:36 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Задача обработки данных с предысторией  (Прочитано 6748 раз)
Hoksmur
Гость
« : Июнь 19, 2013, 06:13 »

 Подскажите, хотя бы в какую сторону смотреть.
 Задача читать данные со звукового входа, ловить условие. Как только наступает  - писать в файл определённый промежуток времени.  Проблемы две:
1) нужно писать и предысторию события - то есть какой-то промежуток времени до его фиксации. Если ловить будет чуть позже наступления, а не в реальном времени - допустимо.
2) данные могут придти в разных форматах: если один канал 8 бит - char, если два канала 16 бит - это уже int (или short) и надо оба канала анализировать.
 Собственно что использовать - вроде как очередь QQueue подходит  - но как контролировать размер? А то поймал событие - попытался прочитать предысторию - а она только несколько значений содержит... QVector?
 Ну и как обойти проблему с разными типами данных? Может ссылки какие, или литературу посоветуйте?
 Сильно не пинайте - C++ и Qt только осваиваю.
 

Записан
Bepec
Гость
« Ответ #1 : Июнь 19, 2013, 06:47 »

2) анализировать и записывать.

По поводу очереди - пойдёт и простой цикличный буфер минуты на три - перезаписывается по мере заполнения.
Записан
Hoksmur
Гость
« Ответ #2 : Июнь 19, 2013, 08:59 »

По поводу очереди - пойдёт и простой цикличный буфер минуты на три - перезаписывается по мере заполнения.
Догадываюсь, что очень общий вопрос, но что посоветуете - использовать готовую очередь Qt (какую из них?) или самому реализовывать? И как контролировать размер буфера? У меня уже задумки делать два последовательных буфера, и при обнаружении события тупо начинать писать с выхода второго.
 Ещё момент - в C++ и Qt в частности - буфер и очередь разные понятия же? (Вот сейчас можно пинать. Обеспокоенный ) Можно ли прочитать из середины буфера, узнать насколько он заполнен, и т. п.?
Записан
Bepec
Гость
« Ответ #3 : Июнь 19, 2013, 09:17 »

Так.. Я бы использовал самописный цикличный буфер, но это моё мнение.

А так всё просто - цикличный буфер на запись последних N минут. И обычный буфер для записи уже после события. Потом просто из цикличного вынимаете данные.

Qt - библиотека C++. Понятия одинаковые.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июнь 19, 2013, 09:21 »

Данные настолько малы (char/short) что использоать Qt контейнер (тем более такой дорогой как QQueue) нет никакого смысла. Просто циклический буфер с четным числом байт + отдельно хранить управляющие сигналы, напр их позицию в буфере
Записан
Hoksmur
Гость
« Ответ #5 : Июнь 19, 2013, 10:05 »

Я так понимаю, очереди на QList построены, а там только указатели к самим данным добавляются. Но отпадают в любом случае - я не смогу данные в середине брать. Если буду сам делать буфер - то на QList удобней, ИМХО.

 А можно ли к QBuffer обращаться как к произвольному массиву данных? То есть, можно ли его в одном случае прочитать  как int, а в другом - как  short, char, в зависимости от настроек? Ещё: порылся - вроде у него можно контролировать заполненность. Есть такие методы: buff.bytesAvailable() buff.bytesToWrite() buff.waitForBytesWritten()  buff.waitForReadyRead()
 Теперь надо это как то с потоком связать - если нет события - выкидываем с конца буфера, если поймали - сигналим второму  обработчику (потоку?), что начинай писать. Если буфер не заполнен - игнорируем.
 А вот с потоками и перегрузкой не разобрался. Помогите, пожалуйста, или подскажите, где хорошо расписано?
Записан
Странник
Гость
« Ответ #6 : Июнь 19, 2013, 10:18 »

Я так понимаю, очереди на QList построены, а там только указатели к самим данным добавляются. Но отпадают в любом случае - я не смогу данные в середине брать. Если буду сам делать буфер - то на QList удобней, ИМХО.

 А можно ли к QBuffer обращаться как к произвольному массиву данных? То есть, можно ли его в одном случае прочитать  как int, а в другом - как  short, char, в зависимости от настроек? Ещё: порылся - вроде у него можно контролировать заполненность. Есть такие методы: buff.bytesAvailable() buff.bytesToWrite() buff.waitForBytesWritten()  buff.waitForReadyRead()
 Теперь надо это как то с потоком связать - если нет события - выкидываем с конца буфера, если поймали - сигналим второму  обработчику (потоку?), что начинай писать. Если буфер не заполнен - игнорируем.
 А вот с потоками и перегрузкой не разобрался. Помогите, пожалуйста, или подскажите, где хорошо расписано?
QQueue наследует QList, так что все его методы доступны, это раз.
QBuffer - просто QIODevice интерфейс для QByteArray, это два.
Из Qt-классов, если уж очень хочется, можете использовать тот самый QByteArray, это три.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Июнь 19, 2013, 11:02 »

А можно ли к QBuffer обращаться как к произвольному массиву данных? То есть, можно ли его в одном случае прочитать  как int, а в другом - как  short, char, в зависимости от настроек?
Это можно делать адресной арифметикой, т.е. базовыми средствами языка

А вот с потоками и перегрузкой не разобрался. Помогите, пожалуйста, или подскажите, где хорошо расписано?
Пусть кто-то даже хочет, но что он ответит про "потоки и перегрузку"?  Улыбающийся Задавайте вопрос конкретнее.
Записан
Hoksmur
Гость
« Ответ #8 : Июнь 19, 2013, 11:46 »

А можно ли к QBuffer обращаться как к произвольному массиву данных? То есть, можно ли его в одном случае прочитать  как int, а в другом - как  short, char, в зависимости от настроек?
Это можно делать адресной арифметикой, т.е. базовыми средствами языка
 Могу попросить набросать пример для чтения буфера в виде signed int?

А вот с потоками и перегрузкой не разобрался. Помогите, пожалуйста, или подскажите, где хорошо расписано?
Пусть кто-то даже хочет, но что он ответит про "потоки и перегрузку"?  Улыбающийся Задавайте вопрос конкретнее.
Верно, спасибо за замечание... Перегрузка операторов и поток (уточнение: не процесс) - например
Код:
qDebug() << "Попугаев: " << i;
То есть обрабатываем поток данных, а собственно << перегруженный оператор сдвига.
 Оператор - откуда он получает данные на вход, куда выдаёт результат? Может ли он "выбросить лишние" данные или продублировать их где-то ещё?
 Поток - как описывается, как обработать данные? Например, в моём случае - читать из буфера только если он более чем на половину заполнен, если нет  - бездействовать.
 То есть то, чем C++ от C (Си) отличается. Объектную модель (класс, экземпляр, метод, свойство), хорошо ли, плохо ли, но понял.
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Июнь 19, 2013, 12:07 »

То есть обрабатываем поток данных, а собственно << перегруженный оператор сдвига.
 Оператор - откуда он получает данные на вход, куда выдаёт результат? Может ли он "выбросить лишние" данные или продублировать их где-то ещё?
 Поток - как описывается, как обработать данные? Например, в моём случае - читать из буфера только если он более чем на половину заполнен, если нет  - бездействовать.
Поток IO - это обобщенное понятие переноса данных от источника к приемнику. Судя по тому что Вы рассказали я не вижу какой-то жизненной необходимости использовать именно поток (хотя это не запрещено). Откуда и куда - просто открываете описание оператора << и видите что это обычная ф-ция. Что там написано - то и будет выполняться, напр поток вводв текста может пропускать пробелы.
Код
C++ (Qt)
int a;
short b;
long c;
strm >> a >> b >> c;
Эта запись удобнее и универсальнее чем напр
Код:
a = file.ReadInt();
b = file.ReadShort();
c = file.ReadLong();
Хотя все равно все ф-ции/операторы чтения должны быть заранее написаны
Записан
Hoksmur
Гость
« Ответ #10 : Июнь 20, 2013, 09:49 »

Для промежуточного результата ввел таймер, чтобы не съедать всю память (и не превысить максимально возможный размер буфера). Набросал приложение, вылетало через некоторое время после сработки таймера, поправил.

Код:
void Widget::startrec()
{
    outFile.setFileName("record.raw");
    outFile.open(QIODevice::WriteOnly|QIODevice::Truncate);

    // prepare to record
    QAudioFormat format;
    QTimer* timer = new QTimer;
    format.setFrequency(8000);
    format.setCodec("audio/pcm");
    format.setChannels(2);
    format.setSampleSize(8);
    format.setByteOrder( QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::UnSignedInt);

    QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
    if (!info.isFormatSupported(format)) {
    qWarning()<<"default format not supported try to use nearest";
    format = info.nearestFormat(format);
    }

    inSignal = new QAudioInput(format, reinterpret_cast<QObject*>(this));
    inSignal->start(&outFile);

    timer->setSingleShot(true);
    connect(timer, SIGNAL(timeout()), this, SLOT(stoprec()));
    timer->setSingleShot(true);
    timer->start(10000);

    qDebug() << "file: " << outFile.size()<< " timer is singleshot:" << timer->isSingleShot();
    ui->checkBox->setChecked(true);
}

void Widget::stoprec()
{
    inSignal->stop();
        qDebug() << "file: " << outFile.size();
    outFile.close();
    delete inSignal;
    ui->checkBox->setChecked(false);
    //timer->stop();
}
всё хорошо отрабатывает. Перенёс в основную программу - приложение аварийно завершается по истечении выставленного времени.
Код:
    // QAudioFormat settings; // Задаем формат
    settings.setFrequency(8000); // Квантование по времени - 8000 замеров/с
    settings.setChannels(1); // 1 канал - моно
    settings.setSampleSize(8); // Глубина кодирования - 16 бит
    settings.setCodec("audio/pcm"); // Формат
    settings.setByteOrder(QAudioFormat::LittleEndian); // Порядок байтов
    settings.setSampleType(QAudioFormat::SignedInt); // Тип данных
...
    audioInput = new QAudioInput(settings);
    // audioInput->setBufferSize(256);
    audioInput->start( &buffer);

    QTimer* timer = new QTimer;
    qDebug() << "Buffer1: " << buffer.bytesAvailable();
    timer->setSingleShot(true);
    connect(timer, SIGNAL(timeout()), this, SLOT(stopRecording()));
    timer->start(100);

void Widget::stopRecording(){

   qDebug() << "2: " << buffer->bytesAvailable();
   if(audioInput!=0)
        if(audioInput->state()==QAudio::ActiveState)
        audioInput->stop();
   qDebug() << "2: " ; //<< buffer->bytesAvailable();
   delete audioInput;
   delete buffer;
}
Записан
Hoksmur
Гость
« Ответ #11 : Июнь 20, 2013, 10:00 »

А этот блок собирается, и даже честно пытается работать, но в панель отладки сыпет множественные сообщения
QAudioInput: IOError
QIODevice::write: ReadOnly device


Код:
    //============= test block
    QByteArray output_bytes;
    QAudioInput* audioInput;
    QAudioFormat settings;
    QBuffer buffer;

    // Set up the format, eg.
    settings.setFrequency(8000);
    settings.setChannels(1);
    settings.setSampleSize(16);
    settings.setCodec("audio/pcm");
    settings.setByteOrder(QAudioFormat::LittleEndian);
    settings.setSampleType(QAudioFormat::UnSignedInt);

    if (!buffer.isOpen())
    buffer.setBuffer(&output_bytes);
    buffer.open(QIODevice::ReadWrite | QIODevice::Append);// :Truncate);

    if (!info.isFormatSupported(settings))
    {
      qWarning() << "default format not supported try to use nearest";
      this->settings = info.nearestFormat(settings);
    }
    audioInput = new QAudioInput(settings, this);
    audioInput->start( &buffer);


При чём строку, где задаю режим открытия сокращал до
 buffer.open(QIODevice::[Read|Write]Only );
 - без изменений. А с файлами - работает.
UPD: Дьявол, как всегда - в мелочах:
reinterpret_cast<QObject*>(this)
« Последнее редактирование: Июнь 20, 2013, 12:02 от Hoksmur » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.072 секунд. Запросов: 23.