Я искал в сети, искал здесь. Я нашел код, который мог скомпилировать, и он отлично работает, но по какой-то причине мой код не воспроизводит никакого звука. Я портирую старую игру на ПК (Windows) и стараюсь сделать ее максимально аутентичной, поэтому я хочу использовать сгенерированные волновые формы. Я в значительной степени скопировал и вставил рабочий код (только добавив несколько голосов), и он все равно не будет работать (даже если тот же самый код для одного голоса работает нормально). Я знаю, что мне не хватает чего-то очевидного, но я просто не могу понять что. Любая помощь будет оценена, спасибо.
Сначала несколько примечаний ... Я искал что-то, что позволило бы мне использовать оригинальную методологию. Исходная система использовала парные байты для музыки (звуковые эффекты - только 2 - обрабатывались в коде.) Байт времени, который отсчитывался каждый раз при вызове подпрограммы, и байт ноты, который воспроизводился до тех пор, пока время не достигло нуля. это было сделано путем вставки в вектор прерывания, окна не позволяют этого, поэтому я установил таймер маршрутизации, который выполняет то же самое. Таймер срабатывает, обновляет дисплей, а затем запускает музыкальную последовательность. Я установил это на определенное время, чтобы у меня было только одно место для настройки времени (чтобы сделать его как можно ближе к исходной последовательности. Музыка представляет собой сгенерированную форму волны (и я дважды проверил математику, и даже проверил сгенерированные данные в режиме отладки), и это выглядит хорошо. Последовательность выглядит хорошо, но на самом деле не воспроизводит звук. Сначала я попробовал SDL2, и этот метод воспроизведения только 1 звука не работает для меня, также , если я не сделаю длительность семпла очень короткой (и звук, производимый таким образом, ужасен), я не смогу согласовать время (он проигрывает весь семпл через собственное прерывание, не позволяя мне вносить коррективы). Кроме того, смешивание трех голосов вместе (когда все они работают с разным таймингом) - это беспорядок. Большинство других движков, которые я исследовал, работают примерно так же, они хотят использовать собственное прерывание обратного вызова и не позволяют мне настраивать его соответствующим образом. почему я начал работать с OpenAL. Он позволяет использовать несколько голосов (источников) и позволяет мне тайминги устанавливаю сам. По совету нескольких форумов я настроил его так, чтобы длина выборки была кратна полному циклу. Во всяком случае, вот код.
int main(int argc, char* argv[])
{
FreeConsole(); //Get rid of the DOS console, don't need it
if (InitLog() < 0) return -1; //Start logging
UINT_PTR tim = NULL;
SDL_Event event;
InitVideo(false); //Set to window for now, will put options in later
curmusic = 5;
InitAudio();
SetTimer(NULL,tim,_FREQ_,TimerProc);
SDL_PollEvent(&event);
while (event.type != SDL_KEYDOWN) SDL_PollEvent(&event);
SDL_Quit();
return 0;
}
void CALLBACK TimerProc(HWND hWind, UINT Msg, UINT_PTR idEvent, DWORD dwTime)
{
RenderOutput();
PlayMusic();
//UpdateTimer();
//RotateGate();
return;
}
void InitAudio(void)
{
ALCdevice *dev;
ALCcontext *cxt;
Log("Initializing OpenAL Audio\r\n");
dev = alcOpenDevice(NULL);
if (!dev) {
Log("Failed to open an audio device\r\n");
exit(-1);
}
cxt = alcCreateContext(dev, NULL);
alcMakeContextCurrent(cxt);
if(!cxt) {
Log("Failed to create audio context\r\n");
exit(-1);
}
alGenBuffers(4,Buffer);
if (alGetError() != AL_NO_ERROR) {
Log("Error during buffer creation\r\n");
exit(-1);
}
alGenSources(4, Source);
if (alGetError() != AL_NO_ERROR) {
Log("Error during source creation\r\n");
exit(-1);
}
return;
}
void PlayMusic()
{
static int oldsong, ofset, mtime[4];
double freq;
ALuint srate = 44100;
ALuint voice, i, note, len, hold;
short buf[4][_BUFFSIZE_];
bool test[4] = {false, false, false, false};
if (curmusic != oldsong) {
oldsong = (int)curmusic;
if (curmusic > 0)
ofset = moffset[(curmusic - 1)];
for (voice = 1; voice < 4; voice++)
alSourceStop(Source[voice]);
mtime[voice] = 0;
return;
}
if (curmusic == 0) return;
//Only 3 voices for music, but have
for (voice = 0; voice < 3; voice ++) { // 4 set asside for eventual sound effects
if (mtime[voice] == 0) { //is note finished
alSourceStop(Source[voice]); //It is, so stop the channel (source)
mtime[voice] = music[ofset++]; //Get the next duration
if (mtime[voice] == 0) {oldsong = 0; return;} //zero marks end, so restart
note = music[ofset++]; //Get the next note
if (note > 127) { //Old HW data was designed for could only
if (note == 255) note = 127; //use values 128 - 255 (255 = 127)
freq = (15980 / (voice + (int)(voice / 3))) / (256 - note); //freq of note
len = (ALuint)(srate / freq); //A single cycle of that freq.
hold = len;
while (len < (srate / (1000 / _FREQ_))) len += hold; //Multiply till 1 interrup cycle
while (len > _BUFFSIZE_) len -= hold; //Don't overload buffer
if (len == 0) len = _BUFFSIZE_; //Just to be safe
for (i = 0; i < len; i++) //calculate sine wave and put in buffer
buf[voice][i] = (short)((32760 * sin((2 * M_PI * i * freq) / srate)));
alBufferData(Buffer[voice], AL_FORMAT_MONO16, buf[voice], len, srate);
alSourcei(openAL.Source[i], AL_LOOPING, AL_TRUE);
alSourcei(Source[i], AL_BUFFER, Buffer[i]);
alSourcePlay(Source[voice]);
}
} else --mtime[voice];
}
}