Load wavs into memory then play sounds asynchronously using Win32 API - c++

I'm writing a simple game, using C++ and the Win32 API. I'd like to load a few sound effects into memory during the initialisation phase (before the game starts). Then I want to be able to trigger those sounds asynchronously during the game.
I've researched a few posts that recommend mmlib, (PlaySound), this works but the examples seem to load from file each time, something like this:
PlaySound("rocket_launch.wav", NULL, SND_FILENAME | SND_ASYNC);
I'd like to load my sounds into memory at the start, then play them whenever. Hopefully I won't need to use a resource file.
How can I do this?

The PlaySound docs say to pass in SND_MEMORY to indicate that the first parameter points to a memory buffer.
So first, load the file into memory, and then pass in the pointer to the buffer, and swap out the SND_FILENAME flag for the SND_MEMORY flag.

To anyone looking for a simple example:
std::string sound = "RIFFªÛ\x5....."; //(Binary of a .wav file)
PlaySoundA(sound.c_str(), NULL, SND_MEMORY | SND_SYNC); //Extracting the binary to a c-style string & playing

Related

Play/Pause/Stop MP3 audio file | (Visual) C++

I want to try and make an MP3 player for Windows. I searched for a function to play audio and found PlaySound() and mciSendString(), from my "research" I found that PlaySound() is only for .wav files, but, for now at least, I want .mp3. I tried mciSendString(), if in the play command, at the end of string I have the parameter "wait"(mciSendString("play audio.mp3 wait", NULL, 0, 0)) then the audio plays fine, but, I can't stop it, I will have to wait(what a surprise) for the audio to end, I found that the wait parameter does that(again, what a surprise). I tried then something like that:
while (!_kbhit()){ //as long as I don't press something
mciSendString("play audio.mp3", NULL, 0, 0); //without the wait
}
I thought that this function might have some sort of pointer that points to where exactly we are in the audio, how much of it we have heard, and with each execution of the command with the same audio, the pointer going, little by little, to the end, to the last "element" of the .mp3 file(note: I don't have the slightest idea how mp3 files and reading from them works)
I seached on the Internet for an example of proper use of mciSendString(), but I couldn't find any clear example/answer or something that works for me, for example, many were saying that still, without the wait it would work, but it didn't. So, here I am now.
What I'm asking: a clear example(code if possible) on how to use mciSendString or other function(s) to do the same thing.
Thank you for listening(reading actually) my problem.

Is it good to use ntdll.dll in a win32 console application?

Short:
In my c++ project i need to read/write extended file properties. I managed it with using alternate data streams (ADS). My problem is, for opening the ADS i need to use the CreateFile API. But it is not fulfilling my needs. NtCreateFile will fullfill all my needs. (Or alternatively NtSetEaFile and NtQueryEaFile) But NtCreateFile is not directly accessible from a win32 console application.
I know i can use this function easily via GetProcAdress. But i like to know the opinion of you all, if i did miss something? Some other libs are using this pattern already, for example Chromium (https://github.com/chromium-googlesource-mirror/chromium/blob/1c1996b75d3611f56d14e2b30e7ae4eabc101486/src/sandbox/src/win_utils.cc function: ResolveNTFunctionPtr)
But im uncertain, because the c++ project is not a hobby project and i ask myself if it is dangerous or not.
I guess NtCreateFile is maybe the securest way to do, because it is well documented and supported by winternl.h header. Especially because this method is unchanged since windows 2000. But what is with NtSetEaFile, NtQueryEaFile which are fitting my needs perfectly. They are only half documented. A documentation for ZwSetEaFile and ZwQueryEaFile exist (unchanged since windows 2000).
Reason why i want to do that:
I want to write and read extended properties from files via ADS. But in case of writing the extended property of a given file the first time, i need to open the file with OPEN_ALWAYS. In case of file is not existing it will create a new file, even if i only access not the content stream of the file. To avoid this i get first the handle of the original file and check with this HANDLE if the file still exist.
But i dont want to blog any file with reduced access rights, because from my point of view that is a very bad pattern. The user needs to have full access to any file any time. Because of that we open all HANDLES with the flag FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE. And now i have the race.
auto hFile = CreateFileW(originalPath, …, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, …).
// this is the little race: if somebody at least rename originalPath the
// second CreateFileW call will cause the creation of a empty file with the
// path originalPath (the old path).
auto hADS = CreateFileW(originalPath + adsName, …, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_ALWAYS, …).
This is a main issue, especially because this happens from time to time in our tests. NtCreateFile will fix it, because i can create the second HANDLE with the help of the first HANDLE. Because of that no race. Or NtSetEaFile and NtQueryEaFile will help, because i only need one HANDLE.
The thing is, that the application needs not to be save for the future, because ADS works only on NTFS anyway. And who knows when NTFS will be exchanged. But i dont want a flaky behaviour. I want to trust this Methods. I I am fine if the API will change in the future and the software needs to adapt to it. But i want to be sure, that all Windows higher or equal then 7 can deal with it. Somebody some experience to share? I would like to hear them very much.
This question is wrong. Your proposed solution for your problem, is not using NtCreateFile, but use CreateFile with dwCreationDisposition set to the OPEN_EXISTING.
From documentation:
OPEN_EXISTING
Opens a file or device, only if it exists. If the specified file or
device does not exist, the function fails and the last-error code is
set to ERROR_FILE_NOT_FOUND.
Simply open file if exists and set whatever you want. If file is renamed, CreateFile returns ERROR_FILE_NOT_FOUND.
THE PROBLEM
Now, to your proposed solution, what is better method or why is not possible use ntdll.dll in win32 console application (???).
Again, your "better" method - GetProcAddress is "wrong" same as using linking against ntdll.dll. In Windows 11, or Windows 12 or Windows 3030 the function may be removed and both solutions (statical vs. dynamical import) will be fail.
It is not really unsecure to use this kind of APIs if their is a documentation. In case of NtSetEaFile, NtQueryEaFile and NtCreateFile you can find a description inside of Microsoft's Doc. (keep in mind NtXxx == ZwXxx)
But this API can change in the future and Microsoft does not guarantee that it will provides the same methods in the next Windows version. If you can, use the public API, because then you are safe. If not it is a case by case decision. In this case the three methods from the API are unchanged since Windows2000. Plus for example NtSetEaFile and NtQueryEaFile is used by Microsoft for WSL (Windows Subsystem for Linux). And especially NtCreateFile is used by a wide range of OpenSource Projects. So it is very unlikely that this API will change.
In my use case another aspect is important. Because I wanted to use ADS, but ADS is only supported by NTFS. So using ADS does not ensure future compatibility as well. So it was very clear for me using NtSetEaFile and NtQueryEaFile.
But how you can use this kind of APIs? Dynamic or static linking is possible. It depends on your needs what is better. In case of static linking you need to download the last WDK (Windows Driver Kit) and link against the ntdll.lib. In case of dynamic linking you can access the dll directly via GetModuleHandle and finding out the address of the method with GetProcAddress. Under Windows ntdll.dll is accessible from any application. In both cases you don't have directly a header file. You have to define the header file by yourself or use WDK to get them.
In my project dynamic linking was the best choice. The reason was, that on every windows the right implementation will be choosen and in case the method is not available i have the chance to deactivate the feature in my software instead of crash. Microsoft is recommending the dynamic way, because of the last reason.
Simple PseudoCode (dynamic case):
typedef struct _FILE_FULL_EA_INFORMATION {
ULONG NextEntryOffset;
UCHAR Flags;
UCHAR EaNameLength;
USHORT EaValueLength;
CHAR EaName[1];
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef NTSTATUS(WINAPI *NtSetEaFileFunction)(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK
IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length);
HMODULE ntdll = GetModuleHandle(L"ntdll.dll");
NtSetEaFileFunction function = nullptr;
FARPROC *function_ptr = reinterpret_cast<FARPROC *>(&function);
*function_ptr = GetProcAddress(ntdll, "NtQueryEaFile");
// function could be used normally.
The other answer is incorrect. The reason is that the reason of my problem is, that I need to use OPEN_ALWAYS. Of course, if you don't need this flag, everything is fine. But in my case there is a point where I needed to create the ADS. And it will not be created without the OPEN_ALWAYS flag.

Tetris background sound

I am making a tetris game using glut libraries.I want to have sound in background.
I have this code.Will it work?
BOOL sndPlaySound(
LPCTSTR lpszSound,
UINT fuSound
);
What I'm doing wrong? How can I solve it?
sndPlaySound is deprecated, and you should use PlaySound from winmm.{lib|dll}
For example:
PlaySound(TEXT("tetris.wav"), NULL, SND_FILENAME | SND_ASYNC);
The last parameter is flags: SND_FILENAME says the first parameter should be interpreted as a file to be loaded. SND_ASYNC says that the function should return immediately, not wait for the sound to finish before returning the control.
Note that this is all winMM library (#include "windows.h"), and has nothing to do with GLUT.

Deleting a bitmap resource in Visual C++

I am trying to delete a resource bitmap through code and am having trouble doing it. Went through several hours of headbanging with google. Here is the code:
int result;
HANDLE h;
h = BeginUpdateResource(L"C:\\Users\\Steve\\Desktop\\stub.exe", FALSE);
result = UpdateResource(h, RT_BITMAP, MAKEINTRESOURCE(IDB_BITMAP2), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0);
EndUpdateResource(h, FALSE);
When I debug, variable "result" ends up being NULL which means that the update didn't go through. Is there something incredibly basic that I'm missing?
Ok, I figured out what went wrong. First off, I used the "GetLastError()" command to help widdle down the possibilities. It gave me an error 0x57 which means ERROR_INVALID_PARAMETER.
When I experimented more, it seems that in the language paramters, I listed "MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)" instead of "MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)". Apparently, resources care about the language you are using even if it's something like a bitmap which doesn't use language.
Once I put in LANG_ENGLISH paramters, it worked. You can find out what language you are using by inspecting the text of the .rc that the resource is using to build.,

Convert bitmap to PNG in-memory in C++ (win32)

Can I convert a bitmap to PNG in memory (i.e. without writing to a file) using only the Platform SDK? (i.e. no libpng, etc.).
I also want to be able to define a transparent color (not alpha channel) for this image.
The GdiPlus solution seems to be limited to images of width divisible by 4. Anything else fails during the call to Save(). Does anyone know the reason for this limitation and how/whether I can work around it?
Update: Bounty
I'm starting a bounty (I really want this to work). I implemented the GDI+ solution, but as I said, it's limited to images with quad width. The bounty will go to anyone who can solve this width issue (without changing the image dimensions), or can offer an alternative non-GDI+ solution that works.
LodePNG (GitHub) is a lib-less PNG encoder/decoder.
I read and write PNGs using libpng and it seems to deal with everthing I throw at it (I've used it in unit-tests with things like 257x255 images and they cause no trouble). I believe the API is flexible enough to not be tied to file I/O (or at least you can override its default behaviour e.g see png_set_write_fn in section on customization)
In practice I always use it via the much cleaner boost::gil PNG IO extension, but unfortunately that takes char* filenames and if you dig into it the png_writer and file_mgr classes in its implementation it seem pretty tied to FILE* (although if you were on Linux a version using fmemopen and in-memory buffers could probably be cooked up quite easily).
On this site the code shows how convert a bitmap to PNG writing it to a file: http://dotnet-snippets.de/dns/gdi-speichern-eines-png-SID814.aspx. Instead of writing to a file, the Save method of Bitmap also supports writing to a IStream (http://msdn.microsoft.com/en-us/library/ms535406%28VS.85%29.aspx). You can create a Stream backed up by memory using the CreateStreamOnHGlobal API function. (http://msdn.microsoft.com/en-us/library/aa378980%28VS.85%29.aspx). The used library, GDI+, is included in Windows up from WindowsXP, and works in Windows up from Windows98. I've never done something with it, just googled around. Looks like you can use that, though.
The CImage class (ATL/MFC) supports saving into PNG format. Like the GDI+ solution, it also supports saving to a stream. Here's some code I use to save it to a CByteArray:
CByteArray baPicture;
IStream *pStream = NULL;
if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) == S_OK)
{
if (image.Save(pStream, Gdiplus::ImageFormatPNG) == S_OK)
{
ULARGE_INTEGER ulnSize;
LARGE_INTEGER lnOffset;
lnOffset.QuadPart = 0;
if (pStream->Seek(lnOffset, STREAM_SEEK_END, &ulnSize) == S_OK)
{
if (pStream->Seek(lnOffset, STREAM_SEEK_SET, NULL) == S_OK)
{
baPicture.SetSize(ulnSize.QuadPart);
ULONG ulBytesRead;
pStream->Read(baPicture.GetData(), ulnSize.QuadPart, &ulBytesRead);
}
}
}
}
pStream->Release();
I don't know if you'd want to use ATL or MFC, though.
I've used GDI+ for saving a bitmap as a PNG to a file. You should probably check out the MSDN info about GDI+ here and in particular this function GdipSaveImageToStream.
This tutorial here will probably provide some help as well.
GDI's (old school, non-plus) has a GetDIBits method that can be asked to output bits using PNG compression (BITMAPINFOHEADER::biCompression == BI_PNG). I wonder if this could be used to create a PNG file? Using GetDIBits to write standard bitmap files is complicated enough - so i suspect this would be even more difficult.
If you want to only use Windows APIs, WIC is the way to accomplish this, and it supports both Bitmaps and PNGs.
It would probably be better to use a library instead of reinventing the wheel yourself.
Look into freeImage