На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела "Программирование звука"
0) Данный раздел предназначен для обсуждения проблем, возникающих при программировании задач, связанных с записью, обработкой, воспроизведением звука. Перед созданием темы подумайте, не будет ли она уместнее в разделах Разработка и тестирование программ, Наши исходники, а особенно Разовые заказы и подработки
1) На Раздел распространяются все Правила форума.Огромная просьба с ними внимательно ознакомиться.
2) Запрещается давать бессмысленные ответы вроде: "Снеси Мастдай", "ХП рулит", "Поставь Линукс" и т.д.
3) Запрещается создавать темы, в которых Вы намереваетесь получить ссылку на кряки, серийники и т.п. Также запрещено любое обсуждение p2p (peer-to-peer) сетей (BitTorrent, eDonkey и т.д.).
4) Реклама всякого рода пресекается беспощадно.
5) Используйте тэг [CODE] для выделения кода программы (непременно с указанием языка программирования - выбрать из списка. В противном случае бессмысленно!). Уважайте тех, кто будет читать ваш код!
6) Если решение вашей проблемы найдено, то не забываем помечать тему специальной функцией "Вопрос решён". Вам всего лишь требуется при написании последнего ответа поставить одну единственную галочку прямо над формой ответа.
7) Если вы хотите получить совет для конкретной платформы/языка программирования, обязательно укажите их в вопросе

8) Если не прикрепляются/не скачиваются файлы, читаем Не прикрепляется / не скачивается файл. Любые обсуждения в данном разделе проблем с приложением файлов считаются оффтопиком! Со всеми вытекающими.

9) NEW! Уважаемые новички! Мы приветствуем Ваше желание научить всех посетителей раздела правильному программированию. Но огромная просьба, перед тем, как писать поучения в старых (последний ответ - "старее" месяца, а особенно, если вопрошавший не появляется на форуме уже не первый месяц, в чем можно убедиться в его профиле) темах, хорошо подумать, будет ли кому-нибудь, кроме Вас cамих, это интересно. Попытки накрутки количества тематических сообщений за счёт поднятия древних неактуальных тем ("некрофилия") будут наказываться по велению левой пятки модераторского состава (см. пп.12, 13 Правил)



Нарушение Правил может повлечь наказание со стороны модераторов.



user posted imageFAQ Раздела user posted imageПоиск в Разделе user posted imageMSDN Library Online | Ваше мнение о модераторах: user posted imageBarazuk user posted imageRikkie
  
> Вывод сигнала произвольной формы на звуковую карту
    Всем привет, есть задача, по выводу сигнала произвольной формы на звуковую карту. Подскажите пожалуйста, в какую сторону рыть? или может, у коего есть какой пример?
      а в чем сложность?
        Цитата Romzecs @
        а в чем сложность?

        Сложность в том, что никогда не сталкивался с выводом генерируемого на ходу буфера на звуковую карту. Если бы надо было вывести ту же вавку или мпег, то все было бы понятно.
        Сообщение отредактировано: BBC -
          ну так и генерируй вавку, в буфер её, а карта глядишь разберется, вавка ведь по сути набор уровней, даже не сжатый
            PlaySound + SND_MEMORY. Структуры wav файла определены где-то в недрах заголовочных файлов winapi (гугл в помощь).
              BBC
              На нашем форуме раз-два кто эти занимался.
              Есть разный API.
              OpenAL
              Audio Stream Input/Output (ASIO)
              DirectSound
              waveOut(waveForm)
              WASAPI

              Собственно вся сложность в том как манипулировать буферами. И как организовать более или менее работу в реальном масштабе времени.
              Как по мне в waveOut это очень сложно и запутанно. Про другие не скажу не пробовал.
              пример работы
              http://msdn.microsoft.com/en-us/library/wi...3(v=vs.85).aspx
              WASAPI Описание туфта. А вот комментарии полезные.
              http://msdn.microsoft.com/en-us/library/wi...6(v=vs.85).aspx
                Да всё проще паренной репы.
                я бы писал на Low Level Windows API.
                Но для этого нужно разобраться с теорией работы с аудиоданными.
                Самый простой способ -
                1. создай заголовок аудио файла(wav).
                2. создай дорожку аудио(8 bit mono, 8000 Gz),значение семплов расчитывается по формулам нужной кривой.
                3. заполни заголовок файла(сумма отсчётов,кол-во дорожек, битрейт и т.д.).
                4. передать адрес файла api функции на проигрывание.
                  Я пытался делать прямоугольные импульсы(частный случай произвольной формы) :) ничего страшного, поищите тут ниже.
                  Проблема в том ,что менее 100мс длительностью фрагмента низя, а мне хотелось 20. :(
                    Если кому интересно, сделал на CLR

                    ExpandedWrap disabled
                          using namespace System::IO;
                          using namespace Microsoft::Win32;
                          public enum ToneType { Sine, Square, Triangle, Sawtooth, User };
                          public ref class WaveHeader
                          {
                          public:
                              static int HeaderSize = 44;
                              int _sampleRate;
                              short _bitsPerSample;
                              bool _stereo;
                              long _numberOfSamples;
                              int _bytesPerSample;
                              WaveHeader(int sampleRate, short bitsPerSample, bool stereo)
                              {
                                  if (sampleRate <= 0)throw "sampleRate", "Sample Rate must be greater than zero.";
                                  if (bitsPerSample != 8 && bitsPerSample != 16)throw "Invalid Bits Per Sample specified.  Currently supported values are [8, 16].", "bitsPerSample";
                                  _sampleRate = sampleRate;
                                  _bitsPerSample = bitsPerSample;
                                  _stereo = stereo;
                                  _bytesPerSample = _bitsPerSample / 8;
                                  if (_stereo)_bytesPerSample *= 2;
                              }
                              property int SampleRate
                              {
                                  int get()
                                  {
                                      return _sampleRate;
                                  }
                              }
                              property short BitsPerSample
                              {
                                  short get()
                                  {
                                      return _bitsPerSample;
                                  }
                              }
                              property bool Stereo
                              {
                                  bool get()
                                  {
                                      return _stereo;
                                  }
                              }
                              property int BytesPerSample
                              {
                                  int get()
                                  {
                                      return _bytesPerSample;
                                  }
                              }
                              property long NumberOfSamples
                              {
                                  long get()
                                  {
                                      return _numberOfSamples;
                                  }
                                  void set(long value)
                                  {
                                      if (value < 0 || value * _bytesPerSample > 0xFFFFFFFF)
                                          throw "NumberOfSamples cannot be less than zero or greater than int.MaxValue * bytesPerSample.";
                       
                                      _numberOfSamples = value;
                                  }
                              }
                              void Write(BinaryWriter ^writer)
                              {
                                  writer->Write(0x46464952); // "RIFF" in ASCII
                                  writer->Write((long)(HeaderSize + (_numberOfSamples * _bitsPerSample * (_stereo ? 2 : 1) / 8)) - 8);
                                  writer->Write(0x45564157); // "WAVE" in ASCII
                                  writer->Write(0x20746d66); // "fmt " in ASCII
                                  writer->Write(16);
                                  writer->Write((short)1);
                                  writer->Write((short)(_stereo ? 2 : 1));
                                  writer->Write(_sampleRate);
                                  writer->Write(_sampleRate * (_stereo ? 2 : 1) * _bitsPerSample / 8);
                                  writer->Write((short)((_stereo ? 2 : 1) * BitsPerSample / 8));
                                  writer->Write(_bitsPerSample);
                                  writer->Write(0x61746164); // "data" in ASCII
                                  writer->Write((long)(_numberOfSamples * _bitsPerSample * (_stereo ? 2 : 1) / 8));
                              }
                          };
                          public ref struct Sample16Bit
                          {
                              short _leftChannel;
                              short _rightChannel;
                              bool _stereo;
                          public:
                              Sample16Bit(short monoChannel)
                              {
                                  _leftChannel = monoChannel;
                                  _rightChannel = monoChannel;
                                  _stereo = false;
                              }
                              Sample16Bit(short leftChannel, short rightChannel)
                              {
                                  _leftChannel = leftChannel;
                                  _rightChannel = rightChannel;
                                  _stereo = true;
                              }
                              Sample16Bit(bool stereo)
                              {
                                  _leftChannel = 0;
                                  _rightChannel = 0;
                                  _stereo = stereo;
                              }
                              property short LeftChannel
                              {
                                  short get()
                                  {
                                      return _leftChannel;
                                  }
                                  void set(short value)
                                  {
                                      _leftChannel = value;
                                      if (!_stereo)_rightChannel = value;
                                  }
                              }
                              property short RightChannel
                              {
                                  short get()
                                  {
                                      return _rightChannel;
                                  }
                                  void set(short value)
                                  {
                                      _rightChannel = value;
                                      if (!_stereo)_leftChannel = value;
                                  }
                              }
                              property bool Stereo
                              {
                                  bool get()
                                  {
                                      return _stereo;
                                  }
                              }
                              virtual bool Equals(Object ^obj)override
                              {
                                  return (obj->GetType()==Sample16Bit::typeid && this->Equals((Sample16Bit ^)obj));
                              }
                              virtual int GetHashCode()override
                              {
                                  int a = this->_leftChannel;
                                  int b = this->_rightChannel;
                       
                                  return ((a << 16) | b);
                              }
                              static bool operator == (Sample16Bit ^a, Sample16Bit ^b)
                              {
                                  return a->Equals(b);
                              }
                              static bool operator !=(Sample16Bit ^a, Sample16Bit ^b)
                              {
                                  return !a->Equals(b);
                              }
                          };
                          public ref class WaveWriter : public IDisposable
                          {
                          private:
                              WaveHeader ^_header;
                              BinaryWriter ^_writer;
                              BinaryReader ^_reader;
                              long _initialStreamPosition;
                              bool _closeUnderlyingStream;
                              bool _disposed;
                          public:
                              WaveWriter(Stream ^output, int sampleRate, short bitsPerSample, bool stereo, bool closeUnderlyingStream)
                              {
                                  if (output == nullptr)throw "Output stream cannot be null.";
                                  _header = gcnew WaveHeader(sampleRate, bitsPerSample, stereo);
                                  _reader = gcnew BinaryReader(output);
                                  _writer = gcnew BinaryWriter(output);
                                  _initialStreamPosition = (long)output->Position;
                                  output->Position += WaveHeader::HeaderSize;
                                  _closeUnderlyingStream = closeUnderlyingStream;
                                  _disposed=false;
                              }
                              property long NumberOfSamples
                              {
                                  long get()
                                  {
                                      ThrowIfDisposed();
                                      return _header->NumberOfSamples;
                                  }
                              }
                              property int SampleRate
                              {
                                  int get()
                                  {
                                      ThrowIfDisposed();
                                      return _header->SampleRate;
                                  }
                              }
                              property WaveHeader ^Header
                              {
                                  WaveHeader ^get()
                                  {
                                      ThrowIfDisposed();
                                      return _header;
                                  }
                              }
                              property long CurrentSample
                              {
                                  long get()
                                  {
                                      ThrowIfDisposed();
                       
                                      return (long)((_writer->BaseStream->Position - WaveHeader::HeaderSize - _initialStreamPosition) / _header->BytesPerSample);
                                  }
                                  void set(long value)
                                  {
                                      ThrowIfDisposed();
                       
                                      if (value < 0)throw "Sample Number must be greater than or equal to zero.";
                                      _writer->BaseStream->Position = _initialStreamPosition + WaveHeader::HeaderSize + (value * _header->BytesPerSample);
                                  }
                              }
                              property BinaryReader ^Reader
                              {
                                  BinaryReader ^get()
                                  {
                                      ThrowIfDisposed();
                                      return _reader;
                                  }
                              }
                              property BinaryWriter ^Writer
                              {
                                  BinaryWriter ^get()
                                  {
                                      ThrowIfDisposed();
                                      return _writer;
                                  }
                              }
                              void Close()
                              {
                                  this->!WaveWriter();
                              }
                              !WaveWriter()
                              {
                                  if (!_disposed)
                                  {
                                      _writer->BaseStream->Position = _initialStreamPosition;
                                      Header->Write(_writer);
                                      if (_closeUnderlyingStream)
                                      {
                                          _writer->Close();
                                          _reader->Close();
                                      }
                                      _disposed = true;
                                  }
                              }
                              ~WaveWriter()
                              {
                                  this->!WaveWriter();
                                  GC::SuppressFinalize(this);
                              }
                          protected:
                              void ThrowIfDisposed()
                              {
                                  if (_disposed)
                                  {
                                      throw "WaveWriter";
                                  }
                              }
                       
                          };
                          public ref class WaveWriter16Bit : WaveWriter
                          {
                          public:
                              WaveWriter16Bit(Stream ^output, int sampleRate, bool stereo)
                                  : WaveWriter(output, sampleRate, 16, stereo, true)
                              {
                              }
                              WaveWriter16Bit(Stream ^output, int sampleRate, bool stereo, bool closeUnderlyingStream)
                                  : WaveWriter(output, sampleRate, 16, stereo, closeUnderlyingStream)
                              {
                              }
                              Sample16Bit ^Read()
                              {
                                  ThrowIfDisposed();
                                  long initialPos = (long)Reader->BaseStream->Position;
                                  try
                                  {
                                      if (Header->Stereo)
                                      {
                                          return gcnew Sample16Bit(Reader->ReadInt16(), Reader->ReadInt16());
                                      }
                                      else
                                      {
                                          return gcnew Sample16Bit(Reader->ReadInt16());
                                      }
                                  }
                                  catch(Exception ^)
                                  {
                                      Reader->BaseStream->Position = initialPos;
                                      throw;
                                  }
                              }
                              void Write(Sample16Bit ^sample)
                              {
                                  ThrowIfDisposed();
                                  long initialPos = (int)Writer->BaseStream->Position;
                                  try
                                  {
                                      Writer->Write(sample->LeftChannel);
                                      if (Header->Stereo)
                                          Writer->Write(sample->RightChannel);
                                  }
                                  catch(Exception ^)
                                  {
                                      Writer->BaseStream->Position = initialPos;
                                      throw;
                                  }
                                  finally
                                  {
                                      if (CurrentSample > Header->NumberOfSamples)
                                          Header->NumberOfSamples = CurrentSample;
                                  }
                              }
                          };
                          public ref class ToneGener
                          {
                          private:
                              System::Media::SoundPlayer ^player;
                              double frequency;
                              int length;
                              short leftVolume;
                              short rightVolume;
                              int toneTypes;
                          public:
                              ToneGener()
                              {
                                  player=nullptr;
                              }
                              property int ToneTypes
                              {
                                  int get() { return toneTypes; }
                                  void set(int value) { toneTypes = value; }
                              }
                              property double Frequency
                              {
                                  double get() { return frequency; }
                                  void set(double value) { frequency = value; }
                              }
                       
                              property int Length
                              {
                                  int get() { return length; }
                                  void set(int value) { length = value; }
                              }
                       
                              property short LeftVolume
                              {
                                  short get() { return leftVolume; }
                                  void set(short value) { leftVolume = value; }
                              }
                       
                              property short RightVolume
                              {
                                  short get() { return rightVolume; }
                                  void set(short value) { rightVolume = value; }
                              }
                              void Play()
                              {
                                  System::IO::MemoryStream ^ms = gcnew System::IO::MemoryStream();
                                  WaveWriter16Bit ^writer = gcnew WaveWriter16Bit(ms, 44100, true, false);
                                  double samplesPerCycle = writer->SampleRate / frequency;
                                  int samplesForNote = (int)(writer->SampleRate);
                                  Sample16Bit ^sample = gcnew Sample16Bit(true);
                                  for (int currentSample = 0; currentSample < samplesForNote; currentSample++)
                                  {
                                      double sampleValueRight = Func(toneTypes, currentSample, samplesPerCycle, rightVolume);
                                      double sampleValueLeft = Func(toneTypes, currentSample, samplesPerCycle, leftVolume);
                                      if (sampleValueRight > 35000)sampleValueRight = 35000;
                                      else if (sampleValueRight < -35000)sampleValueRight = -35000;
                                      if (sampleValueLeft > 35000)sampleValueLeft = 35000;
                                      else if (sampleValueLeft < -35000)sampleValueLeft = -35000;
                                      sample->LeftChannel = (short)sampleValueLeft;
                                      sample->RightChannel = (short)sampleValueRight;
                                      writer->Write(sample);
                                  }
                                  writer->Close();
                                  ms->Position = 0;
                                  player = gcnew System::Media::SoundPlayer(ms);
                                  player->PlayLooping();
                              }
                              void Stop()
                              {
                                  try
                                  {
                                      if (player != nullptr)
                                      {
                                          player->Stop();
                                      }
                                  }
                                  catch(Exception ^)
                                  {
                                  }
                              }
                              void Record()
                              {
                                  System::Windows::Forms::SaveFileDialog ^sf = gcnew System::Windows::Forms::SaveFileDialog();
                                  sf->Filter = "Save opening file|*.wav";
                                  if (sf->ShowDialog()==System::Windows::Forms::DialogResult::OK && (!File::Exists(sf->FileName)))
                                  {
                                      FuncForRecord(sf);
                                  }
                                  else if (File::Exists(sf->FileName))
                                  {
                                      if (sf->ShowDialog()==System::Windows::Forms::DialogResult::OK)
                                      {
                                          File::Delete(sf->FileName);
                                          FuncForRecord(sf);
                                      }
                                  }
                              }
                              void FuncForRecord(System::Windows::Forms::SaveFileDialog ^sf)
                              {
                                  WaveWriter16Bit ^writer = gcnew WaveWriter16Bit(gcnew FileStream(sf->FileName, FileMode::Create), 44100, true, false);
                                  double samplesPerCycle = writer->SampleRate / frequency;
                                  int samplesForNote = (int)(writer->SampleRate * length);
                                  Sample16Bit ^sample = gcnew Sample16Bit(true);
                                  for (int currentSample = 0; currentSample < samplesForNote; currentSample++)
                                  {
                                      double sampleValueRight = Func(toneTypes, currentSample, samplesPerCycle, rightVolume);
                                      double sampleValueLeft = Func(toneTypes, currentSample, samplesPerCycle, leftVolume);
                                      if (sampleValueRight > 0x7FFF)sampleValueRight = 0x7FFF;
                                      else if (sampleValueRight < 0x8FFF)sampleValueRight = 0x8FFF;
                                      if (sampleValueLeft > 0x7FFF)sampleValueLeft = 0x7FFF;
                                      else if (sampleValueLeft < 0x8FFF)sampleValueLeft = 0x8FFF;
                                      sample->LeftChannel = (short)sampleValueLeft;
                                      sample->RightChannel = (short)sampleValueRight;
                                      writer->Write(sample);
                                  }
                              }
                              double Func(int toneTypes, int currentSample, double samplesPerCycle, short volume)
                              {
                                  switch (toneTypes)
                                  {
                                      case 1:
                                          return Math::Sin(currentSample / samplesPerCycle * 2 * Math::PI) * volume;
                                      //break;
                                      case 2:
                                          return Math::Sign(Math::Sin(currentSample / samplesPerCycle * 2 * Math::PI)) * volume;
                                      //break;
                                      case 3:
                                          return Math::Asin(Math::Sin(currentSample / samplesPerCycle * 2 * Math::PI)) * volume;
                                      // break;
                                      case 4:
                                          return (currentSample / samplesPerCycle - Math::Floor(currentSample / (samplesPerCycle) + 1 / 2)) * 2 * volume;
                                      //break;
                                      default:
                                          return 0;
                                      //break;
                                  }
                              }
                          };
                          System::Void SoundClientMain::InitializeSystem()
                          {
                              mToneGener=gcnew ToneGener();
                              mToneGener->Frequency=440;
                              mToneGener->ToneTypes=1;
                              mToneGener->LeftVolume=10000;
                              mToneGener->RightVolume=20000;
                              mToneGener->Play();
                          }
                          System::Void SoundClientMain::DestroySystem()
                          {
                              mToneGener->Stop();
                          }
                      Ребят, а если пример воспроизведения буфера для VB6?
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0841 ]   [ 16 queries used ]   [ Generated: 19.03.24, 10:38 GMT ]