#c #winapi #audio
Вопрос:
Ни один из других ответов, которые я смог найти, похоже, не работает на меня. Я поместил содержимое sound.wav
в такую переменную, чтобы встроить звуковые данные в исполняемый файл, не имея дела с файлами ресурсов:
sound.h
:
std::string sound = R"(RIFFÆø^ WAVEfmt ...)";
Из-за того, что этот звуковой файл длится около 30 секунд, он представляет собой чрезвычайно большую переменную, состоящую из 12 624 строк мусора (что может быть источником проблемы).
Я включил sound.h
main.cpp
, а затем попытался воспроизвести звук с помощью Windows playsoundapi
:
int main() {
std::cout << "Hello" << std::endl;
PlaySoundA(sound.c_str(), nullptr, SND_MEMORY | SND_SYNC);
return 0;
}
Программа просто компилирует, печатает «Привет» и завершает работу с кодом 0 без каких-либо ошибок. Такое ощущение, что на данный момент я перепробовал все, поэтому любая информация помогает.
Комментарии:
1. Если один и тот же код работает при загрузке из файла, содержащего байты, представляющие одни и те же данные, то у вас действительно есть проблема с определением
sound
.2. Как вы выполнили преобразование необработанных двоичных данных в текст? Помните, что не все двоичные байты могут быть представлены в виде символов.
3. Вероятно, вам было бы лучше использовать файл ресурсов, который будет обрабатывать встраивание для вас
4. Вы не проверяете наличие ошибок при вызове PlaySound
Ответ №1:
Вызываемый std::string
вами конструктор создает std::string
объект из исходной последовательности вплоть до первого символа NUL.
Файлы WAVE используют формат файла обмена ресурсами. После идентификатора RIFF
фрагмента идет 4-байтовая последовательность, обозначающая длину. Для файлов размером менее ~16,4 Мбайт четвертый байт равен нулю, поэтому в итоге std::string
получается файл длиной 7. Даже для больших файлов в конечном итоге будут байты со значением 0, что приведет std::string
к хранению усеченной версии входных данных.
У вас есть несколько вариантов решения этой проблемы (от наименее рекомендуемых до наиболее рекомендуемых):
- Используйте
std::string
конструктор, который принимает явныйcount
аргумент. Это позволяет избежать усечения входных данных, как это обычно происходит. - Используйте массив, например
unsigned char const sound[] = R"(RIFF ...)";
. Поскольку C не предоставляет способа описания двоичных литералов, рекомендуется инициализировать каждый элемент числовым значением, напримерunsigned char const sound[] = { 0x52, 0x49, 0x46, 0x46, ... };
. - Свяжите аудиофайл с ресурсами исполняемого образа. Это рекомендуемый способ размещения двоичных активов в исполняемом образе. В игре WAVE Resources есть пример кода для извлечения данных.
Обратите внимание, что PlaySound
имеет возвращаемое значение, которое ваш код игнорирует. Вполне вероятно, что вызов вернется FALSE
так, как вы его вызываете. Наблюдение за ошибками должно быть вашим первым шагом при диагностике проблем.
Комментарии:
1. У меня просто возникли проблемы с файлами ресурсов, но эта информация очень полезна, спасибо!