Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Проиграть бинарный аудио файл


Автор: Vicul 21.10.2010, 11:25
Всем привет,

я хочу получать инфу с микрофона. 
Здесь проблем нет, подключаюсь к /dev/audio и и все записываю в бинарный файл, скажем data.au.
Теперь надо бы переслать его на динамики, сделать на прямую  (типа cat ./data.au >  /dev/audio)не могу,   
ОС выдает, что устройство занято.  Что приходит на ум, это надо  этот файл преобразовать в какой-нибудь звуковой формат
и юзать его через штатный плеер. Вообщем любые идеи, как прослушать полученный файл. 

Автор: bsa 21.10.2010, 13:06
Причем тут C/C++?
Если тебе нужно написать программу, которая будет это делать, то посмотри формат WAV файла. Там ничего сложного, просто заполнишь правильно структуру, запишешь ее перед блоком аудио данных и все.
Если же ты ищешь готовое программное решение, то проще использовать уже готовые программы аудиозахвата, например, Audacity.

Автор: Vicul 21.10.2010, 13:13
>Причем тут C/C++?

потому как все написано у меня на С.  И мне нужно решение на нем. 

За  WAV спасибо, сейчас попробую

Автор: Vicul 21.10.2010, 16:45
Cделал на WAV,  но когда запускаю на плеер - некачественный звук, это так должно быть если напрямую забираешь инфу с /dev/audio ??

Автор: djamshud 21.10.2010, 16:50
А заголовки wav выставлены правильно и соответствуют записанному потоку?

ЗЫ. Раньше можно было просто направить дамп в /dev/dsp, сейчас это тоже можно сделать, но с бубном. Может быть проще будет нагуглить такой бубен?

Автор: Vicul 21.10.2010, 17:18
С дампом не получается,  вот даю все коды, закомнтированные коды в main() это вариант с дампом 

Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>

int g_flagStop;
char* g_pRcvBuffer;
int g_lenBuffer;

struct WAV
{
  char ChankID[4];
  unsigned int ChankSize;
  char Format[4];
  char Subchunk1ID[4];
  unsigned int Subchunk1Size;
  unsigned short  AudioFormat;
  unsigned short NumChannels;
  unsigned int SampleRate;
  unsigned int ByteRate;
  unsigned short  BlockAlign;
  unsigned short BitsPerSample;
  char Subchunk2ID[4];
  unsigned int Subchunk2Size;
};

void* StopThread(void* pParam)
{
  printf("Press Enter for stop:");
  getc(stdin);
  g_flagStop = 1;
  return NULL;
}


void AddRcvBuffer(char chr)
{

  char* pBuffer2 = NULL;
 
  if (g_pRcvBuffer == NULL)
    {
      g_pRcvBuffer = new char[1];
      *g_pRcvBuffer = chr;
      g_lenBuffer = 2;
      return;
    }
  pBuffer2 = new char[3+ g_lenBuffer];
  memset (pBuffer2, 0, g_lenBuffer + 2;
  memcpy(pBuffer2, g_pRcvBuffer,  g_lenBuffer );
  delete [] g_pRcvBuffer;
  *(pBuffer2 +  g_lenBuffer) = chr; 
  g_lenBuffer ++;
  g_pRcvBuffer = pBuffer2;
  return; 

}


int main()
{
  FILE *r = fopen("/dev/audio", "rb");
  //FILE *w = fopen("DATA.AU", "wb");
  pthread_t threadID;
  g_flagStop = 0;
  g_pRcvBuffer = NULL;
  g_lenBuffer = 0;

  pthread_create(&threadID, NULL, &StopThread, NULL);
  //collect data
  while(!g_flagStop) 
    {
      char c = fgetc(r);
      //fputc(c, w);
      AddRcvBuffer(c);
    }
  fclose(r);
  //fclose(w);
  //return 0;
  if (g_pRcvBuffer == NULL)
    {
      printf("No info.");
      return 1;
    }
  else
    {
      //translate to WAV
      FILE* stream = NULL;
      stream = fopen("data.wav", "w");
      if (stream == NULL)
    {
      printf("Cannot open the file data.wav\nError: %s\n",  strerror(errno));
    }
      else
    {
      WAV wav;
      //char chanID[] = 
      memcpy(wav.ChankID,"RIFF", 4);
      memcpy(wav.Format,"WAVE", 4);
      memcpy(wav.Subchunk1ID, "fmt ", 4);
      wav.Subchunk1Size = 16;
      wav. AudioFormat =1;
      wav.NumChannels = 1;//mono
      wav.SampleRate = 8000;
      wav.BitsPerSample = 8;
      wav.BlockAlign = wav.NumChannels * wav.BitsPerSample/8;
      wav.ByteRate = wav.SampleRate * wav.NumChannels * wav.BitsPerSample/8;
      memcpy(wav.Subchunk2ID, "data", 4);
      wav.Subchunk2Size =  g_lenBuffer  * wav.NumChannels * wav.BitsPerSample/8;
      wav.ChankSize = 36 + wav.Subchunk2Size;
      fwrite(&wav, sizeof(WAV), 1, stream);
      fwrite(g_pRcvBuffer, g_lenBuffer, 1, stream);
      fflush(stream);
      fclose(stream);
    }
      delete [] g_pRcvBuffer;
    }
  return 0;
 }

Автор: Vicul 21.10.2010, 17:45
добавил канал в заголовок, стало лучше

Код

      wav.NumChannels = 2;
      wav.SampleRate = 4000;


Шумы ушли, но до идеала далеко.  Может у меня чтото с микрофоном?
Хотя в скайпе работает.

Автор: Vicul 21.10.2010, 18:50
Вообщем поменял  /dev/audio на  /dev/dsp  заработало!

Всем спасибо!

Автор: bsa 21.10.2010, 23:40
Почитай про PulseAudio, может стоит воспользоваться его API.

Автор: xvr 22.10.2010, 10:54
Ошибка в строке 46, должно быть
Код

      g_lenBuffer = 1;

PS. Ваша AddRcvBuffer - это мясорубка для динамической памяти  smile 

Автор: Vicul 24.10.2010, 09:23
Цитата(xvr @  22.10.2010,  10:54 Найти цитируемый пост)
- это мясорубка для динамической памяти

 
Конечно там лажа, за несколько секунд дамп возрастает до 500К, на боевой проге   там нужно делать свопинг. Кусок 
я привел показать,  как я формирую WAV заголовок.   Ладно, проблема не в динамическом буфере, проблема   в другом - как передать  дамп 
обратно на    /dev/dsp пока без левых библиотек?      ОC не даст открыть его для записи.  У вас есть идеи коллега?

Автор: xvr 24.10.2010, 11:33
Цитата(Vicul @  24.10.2010,  09:23 Найти цитируемый пост)
ОC не даст открыть его для записи.  У вас есть идеи коллега?
Поменять права на /dev/dsp


Автор: Vicul 25.10.2010, 07:48
Цитата(xvr @  24.10.2010,  11:33 Найти цитируемый пост)
Поменять права на /dev/dsp


запустил с рутом - не пошло

sudo cat data.au > /dev/dsp 
bash: /dev/dsp: Устройство или ресурс занято

Автор: bsa 25.10.2010, 09:44
Vicul, конечно работать не будет. Так как во всех современных дистрибутивах в качестве системного микшера используется pulseaudio и именно она "занимает" все устройства ввода и вывода звука. Поэтому, я лично, рекомендую использовать именно ее. Ну или что-то, что позволит работать через нее с более простым API (например, OpenAL).

Автор: Vicul 25.10.2010, 10:39
Цитата(bsa @  25.10.2010,  09:44 Найти цитируемый пост)
. Так как во всех современных дистрибутивах в качестве системного микшера используется pulseaudio 


Спасибо, надо переворить это.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)