Форум программистов CodeGuru
18 Январь 2018, 08:07:40 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
Новости:
 
   Начало   Помощь Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема с записью з  (Прочитано 14778 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Kaliban
Новичок
*
Офлайн Офлайн

Сообщений: 5


Просмотр профиля
« : 01 Март 2013, 13:58:14 »

Здравствуйте. Пишу программу, которая будет получать и обрабатывать данные со звуковой карты в виде значений амплитуд.
Попробовал использовать стандартную библиотеку Windows и столкнулся с проблемой: как я понял - после начала записи управление должно передаться функции обратного вызова, в которой по приходу сообщения MM_WIM_DATA должно произойти освобождение буфера и перенос данных в другое место, откуда уже можно с ними работать. Но проблема в том что переход к функции обратного вызова не происходит.
Буду очень благодарен, если кто-то подскажет в чем я ошибся. Заранее спасибо.

Код:
#include "stdafx.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <windows.h>
#include <mmsystem.h>
#include <dsound.h>
#include <conio.h>

#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"dsound.lib")

using namespace std;


HWAVEIN hWaveIn;
WAVEFORMATEX WaveFormat;

WAVEHDR WaveHdr;

LPWSTR buff;

void CALLBACK hWnd(HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
switch (uMsg)
  {
    case MM_WIM_DATA:
waveInUnprepareHeader(hWaveIn, &WaveHdr, sizeof(WAVEHDR));
//WaveHdr.lpData - указывают на буфер, где хранять записанные данные.
//После вызова waveInUnprepareHeader ими можно распоряжаться

//Тут будут действия с данными

free(WaveHdr.lpData);
waveInClose(hWaveIn);

      break;
  }
return ;
}



int _tmain(int argc, _TCHAR* argv[])
{
//Инициализация устройства записи

WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
WaveFormat.nChannels = 1;
WaveFormat.nSamplesPerSec = 16000L;
WaveFormat.nBlockAlign = 2;
WaveFormat.nAvgBytesPerSec = WaveFormat.nSamplesPerSec*WaveFormat.nBlockAlign;
WaveFormat.wBitsPerSample = 16;
WaveFormat.cbSize = 0;

MMRESULT mmRes = waveInOpen(&hWaveIn, WAVE_MAPPER, &WaveFormat, (DWORD)hWnd, 0L, CALLBACK_WINDOW);

waveInGetErrorText(mmRes, buff, 100);
cout<<buff<<endl;
////

//Подготовка буфера
ULONG BufferSize = WaveFormat.nBlockAlign*WaveFormat.nSamplesPerSec*2; //секунды
WaveHdr.lpData = (LPSTR)malloc(BufferSize);
WaveHdr.dwBufferLength = BufferSize;

waveInPrepareHeader(hWaveIn, &WaveHdr, sizeof(WAVEHDR));

waveInAddBuffer(hWaveIn, &WaveHdr, sizeof(WAVEHDR));
////

//Запись
waveInStart(hWaveIn);
////

system("PAUSE");
return 0;
}
Записан
3V
Администратор
Ветеран
*****
Офлайн Офлайн

Сообщений: 1347



Просмотр профиля WWW
« Ответ #1 : 01 Март 2013, 19:10:34 »

Подозреваю, что вместо
Код:
WaveFormat.cbSize = 0;
стоит написать:
Код:
WaveFormat.cbSize = sizeof(WaveFormat);


З.Ы. На всякий случай: waveInOpen, Processing the MM_WOM_DONE Message.

Отсюда: http://www.codeproject.com/Articles/12574/Simple-audio-recording-program можно скачать исходники приложения для записи аудио через wave*-функции (для скачивания нужна рега). Там в принципе, то что нужно.
« Последнее редактирование: 01 Март 2013, 19:16:05 от 3V » Записан

Kaliban
Новичок
*
Офлайн Офлайн

Сообщений: 5


Просмотр профиля
« Ответ #2 : 03 Март 2013, 11:36:57 »

Подозреваю, что вместо
Код:
WaveFormat.cbSize = 0;
стоит написать:
Код:
WaveFormat.cbSize = sizeof(WaveFormat);


З.Ы. На всякий случай: waveInOpen, Processing the MM_WOM_DONE Message.

Отсюда: http://www.codeproject.com/Articles/12574/Simple-audio-recording-program можно скачать исходники приложения для записи аудио через wave*-функции (для скачивания нужна рега). Там в принципе, то что нужно.
Большое спасибо, эта проблема разрешилась. Вот только не могу теперь понять как оперировать записанными данными. Пытаюсь записать в файл:
Код:
void CALLBACK hWnd(HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
switch (uMsg)
 {
    case MM_WIM_DATA:
waveInUnprepareHeader(hWaveIn, &WaveHdr, sizeof(WAVEHDR));
//WaveHdr.lpData - указывают на буфер, где хранять записанные данные.
//После вызова waveInUnprepareHeader ими можно распоряжаться

DWORD writen=0;
const HANDLE hFile=CreateFile L"test.txt",GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
WriteFile(hFile,WaveHdr.lpData,WaveHdr.dwBytesRecorded,&writen,0);
FlushFileBuffers(hFile);
CloseHandle(hFile);
free(WaveHdr.lpData);
waveInClose(hWaveIn);
      break;
  } 

return ;
}

Но в файл пишутся кракозябры. Это я где-то ошибся или нужно эти данные как-то расшифровывать? Мне нужно получить просто мгновенные значения амплитуд.
Очень надеюсь на вашу помощь.


Записан
Kaliban
Новичок
*
Офлайн Офлайн

Сообщений: 5


Просмотр профиля
« Ответ #3 : 03 Март 2013, 19:40:36 »

Здравствуйте. Мне в программе необходимо реализовать получение мгновенных значений амплитуд со звуковой карты, пока что просто получение их в понятном виде, потоком в реальном времени.
 Я перепробовал все: функции стандартной мультимедиа библиотеки, bass.dll и DirectSound. Но везде выходит одно - я записываю определенного размера буфер и не знаю что с ним дальше делать. Совершенно не понятно в каком виде в нем хранятся данные и как их получить в виде удобоваримых значений в децибелах или чем то еще.

 Возникают такие вопросы:
 Как расшифровывать получаемые данные?
 Если используются буферы, то как реализовать что бы получение и обработка данных шли потоком в реальном времени?
 Возможно ли вообще обойти буферы и напрямую потоком получать значения амплитуд?

 Очень надеюсь на вашу помощь, а то совсем уже зашел в тупик.
Записан
3V
Администратор
Ветеран
*****
Офлайн Офлайн

Сообщений: 1347



Просмотр профиля WWW
« Ответ #4 : 06 Март 2013, 23:26:14 »

Но в файл пишутся кракозябры. Это я где-то ошибся или нужно эти данные как-то расшифровывать? Мне нужно получить просто мгновенные значения амплитуд.

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

Поскольку в структуру WaveFormat заносятся значения:
Код:
WaveFormat.nSamplesPerSec = 16000L;
WaveFormat.nBlockAlign = 2;
WaveFormat.nAvgBytesPerSec = WaveFormat.nSamplesPerSec*WaveFormat.nBlockAlign;
WaveFormat.wBitsPerSample = 16;
надо полагать, что в секунду делается 16000 семплов. При этом значение амплитуды 16-и битное (WaveFormat.wBitsPerSample = 16). Вот насчет WaveFormat.nBlockAlign - фик его знает... наверно это по границе скольких байт выравнивать значение амплитуды ?

Получается, что если записанный файл читать по 2 байта, это и будут нужные значения амплитуд.
Записан

Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!