LINUX.ORG.RU

Проблема с чтением wav файла?

 ,


0

1

Вообщем в винде работает код, а в убунте нет

//Sound.h
#pragma once
#include <AL/al.h>
#include <AL/alc.h>
#include <stdio.h>
#include <iostream>
#include <string>
#ifdef _WIN32
	#include <io.h>
	#include <Windows.h>
#else
	#include <unistd.h>
	#include <fcntl.h>
	#include <sys/stat.h>
#endif // _WIN32

struct WAVHEADER
{
	// WAV-формат начинается с RIFF-заголовка:
	// Содержит символы "RIFF" в ASCII кодировке
	// (0x52494646 в big-endian представлении)
	char chunkId[4];
	// 36 + subchunk2Size, или более точно:
	// 4 + (8 + subchunk1Size) + (8 + subchunk2Size)
	// Это оставшийся размер цепочки, начиная с этой позиции.
	// Иначе говоря, это размер файла - 8, то есть,
	// исключены поля chunkId и chunkSize.
	unsigned long chunkSize;
	// Содержит символы "WAVE"
	// (0x57415645 в big-endian представлении)
	char format[4];
	// Формат "WAVE" состоит из двух подцепочек: "fmt " и "data":
	// Подцепочка "fmt " описывает формат звуковых данных:
	// Содержит символы "fmt "
	// (0x666d7420 в big-endian представлении)
	char subchunk1Id[4];
	// 16 для формата PCM.
	// Это оставшийся размер подцепочки, начиная с этой позиции.
	unsigned long subchunk1Size;
	// Аудио формат, полный список можно получить здесь http://audiocoding.ru/wav_formats.txt
	// Для PCM = 1 (то есть, Линейное квантование).
	// Значения, отличающиеся от 1, обозначают некоторый формат сжатия.
	unsigned short audioFormat;
	// Количество каналов. Моно = 1, Стерео = 2 и т.д.
	unsigned short numChannels;
	// Частота дискретизации. 8000 Гц, 44100 Гц и т.д.
	unsigned long sampleRate;
	// sampleRate * numChannels * bitsPerSample/8
	unsigned long byteRate;
	// numChannels * bitsPerSample/8
	// Количество байт для одного сэмпла, включая все каналы.
	unsigned short blockAlign;
	// Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д.
	unsigned short bitsPerSample;
	// Подцепочка "data" содержит аудио-данные и их размер.
	// Содержит символы "data"
	// (0x64617461 в big-endian представлении)
	char subchunk2Id[4];
	// numSamples * numChannels * bitsPerSample/8
	// Количество байт в области данных.
	unsigned long subchunk2Size;
	// Далее следуют непосредственно Wav данные.
};
struct Sounds
{
	unsigned int* buffer;
	unsigned int* source;
	std::string* Name;
	int* number;
};
class Sound
{
public:
	Sound();
	int Init();
	int Play(int src);
	int Stop(int src, bool force);
	int StopAll();
	void SetPlay(int num);
	virtual ~Sound();
private:
protected:
	ALCdevice* dev;
	ALCcontext* ctx;
	int state;
	unsigned char* buf;
	unsigned int size_, freq;
	int format;
	int file;
	int org;
	Sounds *sounds;
	int CounterSounds, CountSounds;
};
//Sound.cpp
#include "Sound.h"
#ifdef _WIN32
	#pragma warning(disable : 4996)
	#pragma comment(lib,"OpenAL32_.lib")
#endif

Sound::Sound()
{
	CountSounds = 5;
	sounds = new Sounds[CountSounds];
	sounds->Name = new std::string[CountSounds];
	for (int i = 0; i < CountSounds; i++)
	{
		sounds->Name[i] = "";
	}
	sounds->buffer = new unsigned int[CountSounds];
	sounds->source = new unsigned int[CountSounds];
	sounds->number = new int[CountSounds];
	CounterSounds = 0;
}
int Sound::Init()
{
	dev = alcOpenDevice(0);
	ctx = alcCreateContext(dev, 0);
	alcMakeContextCurrent(ctx);
	alGenBuffers(CountSounds, sounds->buffer);
	alGenSources(CountSounds, sounds->source);
	sounds->Name[0] = "content//test.wav";
	sounds->Name[1] = "content//konga.wav";
	sounds->Name[2] = "content//internet.wav";
	sounds->Name[3] = "content//winner.wav";
	sounds->Name[4] = "content//coin.wav";
	for (int j = 0; j < CountSounds; j++)
	{
		FILE* file_;
#ifdef _WIN32
		errno_t err;
		err = fopen_s(&file_,sounds->Name[j].c_str(), "rb");
		if (err)
		{
			printf_s("Failed open file, error %d", err);
			return 0;
		}
#else
        file_=fopen(sounds->Name[j].c_str(), "rb");
#endif
		WAVHEADER header;
#ifdef _WIN32
		fread_s(&header, sizeof(WAVHEADER), sizeof(WAVHEADER), 1, file_);
#else
		fread(&header, sizeof(WAVHEADER), 1, file_);
#endif

		printf("audioformat:%d\n", header.audioFormat);
		printf("bitsPerSample:%d\n", header.bitsPerSample);
		printf("blockAlign:%d\n", header.blockAlign);
		printf("byteRate:%lu\n", header.byteRate);
		printf("chunkId:%s\n", header.chunkId);
		printf("chunkSize:%lu\n", header.chunkSize);
		printf("format:%s\n", header.format);
		printf("numCannels:%d\n", header.numChannels);
		printf("sampleRate:%lu\n", header.sampleRate);
		printf("subchunk1Id:%s\n", header.subchunk1Id);
		printf("subchunk1Size:%lu\n", header.subchunk1Size);
		printf("subchunk2Id:%s\n", header.subchunk2Id);
		printf("subchunk2Size:%lu\n", header.subchunk2Size);
		fclose(file_);
		if (header.numChannels == 1)
		{
			if (header.subchunk1Size == 16)
				format = AL_FORMAT_MONO16;
			else
				format = AL_FORMAT_MONO8;
		}
		else
		{
			if (header.subchunk1Size == 16)
				format = AL_FORMAT_STEREO16;
			else
				format = AL_FORMAT_STEREO8;
		}
#ifdef _WIN32
		file = open(sounds->Name[j].c_str(), _A_ARCH);
#else
		file = open(sounds->Name[j].c_str(), O_RDONLY);
#endif // _WIN32
		if (file == -1)
		{
			printf("Open failed on input file: %s\n",sounds->Name[j].c_str());
#ifdef _WIN32
			wchar_t path[MAX_PATH];
			GetCurrentDirectory(sizeof(path), path);
			std::wcout << path << std::endl;
#endif // _WIN32
		}
		org = 0;
		lseek(file,0,org);
		std::cout<<"hchs="<<header.subchunk2Size<<std::endl;
		buf = new unsigned char[header.subchunk2Size];
		read(file, buf, header.subchunk2Size);
		org = 1;
		alBufferData(sounds->buffer[j], format, buf, header.subchunk2Size, header.sampleRate);
		delete buf;
		alSourcei(sounds->source[j], AL_BUFFER, sounds->buffer[j]);
		close(file);
	}

	return 0;
}
int Sound::Play(int src)
{
	alGetSourcei(sounds->source[src], AL_SOURCE_STATE, &state);
	if (state == AL_PLAYING)
		return 0;
	alSourcePlay(sounds->source[src]);
	return 1;
}
int Sound::Stop(int src, bool force)
{
	alGetSourcei(sounds->source[src], AL_SOURCE_STATE, &state);
	if (state == AL_PLAYING || force)
		alSourceStop(sounds->source[src]);
	return 0;
}
int Sound::StopAll()
{
	for (int i = 0; i < CountSounds; i++)
		Stop(i, false);
	return 0;
}
Sound::~Sound()
{
	alDeleteSources(CountSounds, sounds->source);
	alDeleteBuffers(CountSounds, sounds->buffer);
	delete sounds;
	delete buf;
	alcMakeContextCurrent(0);
	alcDestroyContext(ctx);
	alcCloseDevice(dev);
	org = 2;
}
//main.cpp
#include "Sound.h"
void main()
{
        Sound *Sound_ = new Sound();
	Sound_->Init();
        Sound_->Play(2);
}
Проблема в то что один из аргументов WAVEHEADER при чтении огромный выдает огромные значение из-за чего памяти не хватает и программа завершается



Последнее исправление: bad_master (всего исправлений: 6)

Читай структуру поэлементно. Одним куском — плохой стиль. man выравнивание (а может и ещё какое implementation defined, в любом случае лучше не связываться).

alegz ★★★★
()
Последнее исправление: alegz (всего исправлений: 1)

у тебя нет упаковки данных в твоём хэдере. и компилятор делает выравнивание при выделении полей.

Iron_Bug ★★★★★
()

и да, не надо ничего поэлементно читать, это какой-то бред. просто поставь упаковку через pragma.

Iron_Bug ★★★★★
()

Во-первых, у тебя в структуре заголовка используются типы нефиксированной длины. Например, посмотри какая у тебя длина unsigned long и какая длина этого поля в WAV файле. Во-вторых, выравнивание. В-третьих, endianess.

Никогда не надо читать в структуру, даже с фиксированными типами и костылями типа #pragma pack, это никогда не переносимо. Читай в массив байт, оттуда заполняй структуру используя битовые операции и сдвиги.

slovazap ★★★★★
()

один из аргументов WAVEHEADER при чтении огромный выдает огромные значение

Вангую: 32 vs 64 бита. Избавляйтесь от long’ов.

bugfixer ★★★★
()
Ответ на: комментарий от slovazap

это никогда не переносимо.

Слишком сильное утверждение.

Читай в массив байт,

Правильно выравненный массив байт.

оттуда заполняй структуру используя битовые операции и сдвиги.

Waste of CPU cycles. Закастили и покатились. Часть вещей за’bswap’ить возможно придётся.

bugfixer ★★★★
()
Ответ на: комментарий от slovazap

это никогда не переносимо

вот не надо нагонять туман. это всегда работало. много лет пишу софт для железа и сетей, проблем нет.

только вот использование дефолтных типов и отсутствие упаковки умножает всё на ноль.

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 1)
Ответ на: комментарий от thunar

короче сложно это все что вы насоветовали, взял простую реализацию alut отсюда https://gist.github.com/desperius/5082114 в винде плохо, не отыщешь данный lib и dll файлы для сборки а в линухе есть и это хорошо!

bad_master
() автор топика

Хотел ответить, потом увидел кто автор и решил не кормить, потом увидел что внизу уже ответили всё.

firkax ★★★★★
()

Да не поможет упаковка. Не стоило брать long в линуксе он 64 битный, в винде -32 битный, поменяй на int и все должно зароботать.

CrackedMind
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.