Войти
ПрограммированиеФорумЗвук

Проблема с OpenAL, а точнее с ov_read

#0
0:01, 27 янв. 2009

Возникла проблема с ov_read. Я пытаюсь проиграть OGG файл в потоковом режиме, но при считывании данных из файла c помощью ov_read для обновления данных в буфере возникает ошибка Memory Access Violation и программа вылетает.

Вот функция загрузки OGG, загрузка происходит без ошибок

bool CSoundSystem::loadOgg(unsigned int& position, char* file_path, bool stream)
{
  int current_section = 0;
  vorbisfile = new OggVorbis_File;
  int bites_read;
  unsigned int fsize = 0;
  SOUNDSYSTEM_SOUND_DATA soundData;
  SOUNDSYSTEM_STREAM_SOUND_DATA soundStreamData;

  FILE* f = fopen(file_path, "rb");
  
  if(f == NULL)
  {
    return false;
  }

  // Устанавливаем Callback функции для работы с OGG файлом
  ov_callbacks cb;
  cb.close_func = close_ogg;
  cb.read_func = read_ogg;
  cb.seek_func = seek_ogg;
  cb.tell_func = tell_ogg;

  // Устанавливаем Callback функции
  if(ov_open_callbacks(f, vorbisfile, NULL, 0, cb) < 0)
  {
    return false;
  }

  // Информация о загружаемом OGG файле
  vorbis_info *vi = ov_info(vorbisfile, -1);

  ALenum format;
  // Устанавливаем частоту воспроизведения
  ALsizei freq = vi->rate;

  // Устанавливаем формат MONO 16 Bit или STEREO 16 Bit
  if(vi->channels == 1)
  {
    format = AL_FORMAT_MONO16;
  }else
  {
    format = AL_FORMAT_STEREO16;
  }

  // Заводим буфер для PCM данных
  this->m_PCMBuffer = new char[SOUND_BUFFER];

  // Режим загрузки файла
  if(stream == false)
  {
    // Полная загрузка

    // Признак конца файла
    bool eof = false;
    
    // Скоко байт считано из файла
    unsigned long total_read;

    // Считывание из файла PCM данных, и подсчет размера файла
    while(!eof)
    {
      total_read = 0;
      while(total_read < SOUND_BUFFER)
      {
        bites_read = ov_read(vorbisfile, this->m_PCMBuffer + total_read, SOUND_BUFFER - total_read, 0, 2, 1, ¤t_section);
        if(bites_read == 0) break;
        if(bites_read > 0)
        {
          total_read += bites_read;
        }
      }

      if(total_read == 0)
      {
        eof = true;
      }

      // Общий размер, который понадобиться для раскодированых PCM данных
      fsize += total_read;
    }

    // Очистка ресурсов и закрытие файла
    ov_clear(vorbisfile);
    delete [] this->m_PCMBuffer;

    current_section = 0;

    // Открытие файла
    FILE* f = fopen(file_path, "rb");
    // Установка callback функций и выдиление ресурсов для PCM буфера
    this->m_PCMBuffer = new char[fsize];
    ov_open_callbacks(f, vorbisfile, NULL, 0, cb);
    
    // Загрузка OGG файла
    total_read = 0;
    while(total_read < fsize)
    {
      bites_read = ov_read(vorbisfile, this->m_PCMBuffer + total_read, fsize - total_read, 0, 2, 1, ¤t_section);
      if(bites_read == 0) break;
      if(bites_read > 0)
      {
        total_read += bites_read;
      }
    }

    ov_clear(vorbisfile);
    // Создание буфера и источника OpenAL
    alGenBuffers(1, &soundData.buffer);
    alGenSources(1, &soundData.source);
    // Копируем данные в буфер OpenAL
    alBufferData(soundData.buffer, format, (ALvoid*) this->m_PCMBuffer, fsize, freq);
    // Привязываем буфер к источнику
    alSourceQueueBuffers(soundData.source, 1, &soundData.buffer);

    soundData.format = format;
    soundData.freq = freq;

    this->m_soundData.push_back(soundData);

    position = this->m_soundData.size() - 1;
  }
  else
  {
    // Потоковая загрузка
    soundStreamData.format = format;
    soundStreamData.freq = freq;
    soundStreamData.f = f;
    soundStreamData.vorbisfile = new OggVorbis_File;
    
    alGenBuffers(1, &soundStreamData.secondBuffer);

    bool eof = false;
    
    unsigned long total_read;

    total_read = 0;
    while(total_read < SOUND_BUFFER)
    {
      bites_read = ov_read(vorbisfile, this->m_PCMBuffer + total_read, SOUND_BUFFER - total_read, 0, 2, 1, ¤t_section);
      if(bites_read == 0) break;
      if(bites_read > 0)
      {
        total_read += bites_read;
      }
    }
    
    current_section = 0;

    alGenBuffers(1, &soundStreamData.buffer);
    alGenSources(1, &soundStreamData.source);
    alBufferData(soundStreamData.buffer, format, (ALvoid*) this->m_PCMBuffer, total_read , freq);
  
    total_read = 0;
    while(total_read < SOUND_BUFFER)
    {
      bites_read = ov_read(vorbisfile, this->m_PCMBuffer + total_read, SOUND_BUFFER - total_read, 0, 2, 1, ¤t_section);
      if(bites_read == 0) break;
      if(bites_read > 0)
      {
        total_read += bites_read;
      }
    }

    alBufferData(soundStreamData.secondBuffer, format, (ALvoid*) this->m_PCMBuffer, total_read , freq);

    ALuint *buffers = new ALuint[2];
    buffers[0] = soundStreamData.buffer;
    buffers[1] = soundStreamData.secondBuffer;
    alSourceQueueBuffers(soundStreamData.source, 2, buffers);

    soundStreamData.vorbisfile = vorbisfile;
    soundStreamData.current_section = current_section;
    this->m_loadMutex = true;

    while(this->m_threadMutex) ;

    this->m_soundStreamData.push_back(soundStreamData);

    position = this->m_soundStreamData.size() - 1;

    this->m_loadMutex = false;
  }

  delete [] this->m_PCMBuffer;
  if(alGetError() != AL_NO_ERROR) return false;

  return true;
}

А вот функция обновления состояния для потоковых звуков, ошибка возникает именно в этой функции

bool CSoundSystem::thread()
{
  int count_processed;
  ALuint buffer;
  m_PCMBuffer = new char[SOUND_BUFFER];
  long total_read = 0;
  int bites_read;
  int current_section = 0;

  while(this->m_destroySystem == false)
  {
    while(this->m_loadMutex);

    unsigned int count = this->m_soundStreamData.size();

    this->m_threadMutex = true;

    for(unsigned int i = 0; i != count; i++)
    {
      this->m_threadMutex = true; 

      if(this->m_loadMutex)
      {
        this->m_threadMutex = false;
        while(this->m_loadMutex);
        this->m_threadMutex = true;
      }

      alGetSourcei(this->m_soundStreamData[i].source, AL_BUFFERS_PROCESSED, &count_processed);

      while(count_processed --)
      {

        alSourceUnqueueBuffers(this->m_soundStreamData[i].source, 1, &buffer);

        long total_read = 0;
        int bites_read;

        while(total_read < SOUND_BUFFER)
        {
          bites_read = ov_read(this->m_soundStreamData[i].vorbisfile, m_PCMBuffer + total_read, SOUND_BUFFER - total_read, 0, 2, 1, &this->m_soundStreamData[i].current_section); // ERRROR!!!!!!!!!!!!!!!!!!!!!!!!
          if(bites_read == 0) break;
          if(bites_read > 0)
          {
            total_read += bites_read;
          }
        }
        
        printf("Exit first loop\n");

        if(this->m_soundStreamData[i].loop && total_read == 0)
        {
          ov_pcm_seek(this->m_soundStreamData[i].vorbisfile, 0);

          total_read = 0;
          while(total_read < SOUND_BUFFER)
          {
            bites_read = ov_read(this->m_soundStreamData[i].vorbisfile, m_PCMBuffer + total_read, SOUND_BUFFER - total_read, 0, 2, 1, ¤t_section);
            if(bites_read == 0) break;
            if(bites_read > 0)
            {
              total_read += bites_read;
            }
          }
        }

        if(total_read != 0)
        {
          alBufferData(buffer, this->m_soundStreamData[i].format, (ALvoid*) m_PCMBuffer, total_read, this->m_soundStreamData[i].freq);
          alSourceQueueBuffers(this->m_soundStreamData[i].source, 1, &buffer);
        }
      }

      if(this->m_destroySystem)
      {
        this->m_threadMutex = false;
        return true;
      }

      this->m_threadMutex = false;
    }

    this->m_threadMutex = false;
  }

  delete [] m_PCMBuffer;

  return true;
}

SOUND_BUFFER = 5 Мегабайтам

Помогите кто сталкивался с такой проблемой :(


#1
11:08, 27 янв. 2009

this->m_threadMutex = false;

Во первых как объявлена переменная m_threadMutex? ( должна быть объявлена как volatile bool m_threadMutex; )

во вторых использовал бы ты лучше критическую секцию или мютекс.

PS: нафигаж тебе при каждом оборащении this писать... читать код невозможно.

#2
19:21, 27 янв. 2009

Стас
>Во первых как объявлена переменная m_threadMutex? ( должна быть объявлена как volatile bool m_threadMutex; )

Да она так и обьявлена volatile bool m_threadMutex;

Даже если не использовать потоки, а функцию выполнять вызывать для обновления состояния, то программа вылетает всеравно

>PS: нафигаж тебе при каждом оборащении this писать... читать код невозможно.

Ужастная привычка, после рабочего дня на PHP

Прошло более 3 лет
#3
17:28, 30 авг. 2012

M0nstr0
както починил? :)

ПрограммированиеФорумЗвук

Тема в архиве.