 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Deltron Z Expert Cheater
Reputation: 1
Joined: 14 Jun 2009 Posts: 164
|
Posted: Mon Oct 11, 2010 11:07 pm Post subject: Recording and Playing audio. |
|
|
I've been looking around for quite a lot now... usually I use MSDN or other sources, but in this case there's not really any good documented sources.
I understand using mciSendString and mciSendCommand can help me record and play sounds easily, but I couldn't get the sound buffer data, and besides, these were slow for me. I've found a source code that is recording, playing and saving the audio to a file, it took a few seconds just to initialize each operation, but I need to work faster because I am trying to create a simple Skype-like software, for now, just a console that records a few seconds and sends the information through the internet.
So far I've managed to understand (poorly) the wave* APIs and successfuly retrived the buffer's content.
Here's what I've done so far:
Code: | #define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <mmsystem.h>
#include <stdio.h>
#pragma comment(lib, "winmm.lib")
#define BUFFER_SIZE 4096 * 2
void Error(LPCSTR Description, DWORD Error)
{
printf("%s (%u)\n", Error);
}
DWORD Record(/*DWORD dwMilliSeconds*/)
{
DWORD bytesWritten;
DWORD dwReturn;
HANDLE hFile;
HWAVEIN hWaveIn;
WAVEHDR waveHeader;
WAVEFORMATEX waveFormat = {
WAVE_FORMAT_PCM, //wFormatTag;
1, //nChannels;
11025, //nSamplesPerSec;
11025, //nAvgBytesPerSec;
1, //nBlockAlign;
8, //wBitsPerSample,
0 };
dwReturn = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, NULL, NULL, CALLBACK_NULL);
if (dwReturn != ERROR_SUCCESS)
{
Error("waveInOpen", dwReturn);
return dwReturn;
}
waveHeader.dwFlags = 0;
waveHeader.dwBufferLength = BUFFER_SIZE;
waveHeader.lpData = new char[waveHeader.dwBufferLength];
dwReturn = waveInPrepareHeader(hWaveIn, &waveHeader, sizeof(waveHeader));
if (dwReturn != ERROR_SUCCESS)
{
Error("waveInPrepareHeader", dwReturn);
return dwReturn;
}
dwReturn = waveInAddBuffer(hWaveIn, &waveHeader, sizeof(waveHeader));
if (dwReturn != ERROR_SUCCESS)
{
Error("waveInAddBuffer", dwReturn);
return dwReturn;
}
dwReturn = waveInStart(hWaveIn);
for (int i = 0; i < 100; i++)
{
Sleep(100);
if ((waveHeader.dwFlags & WHDR_DONE) == WHDR_DONE)
break;
}
printf("%u\n", waveHeader.dwBytesRecorded);
hFile = CreateFile(TEXT("recording.wav"), GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
//Format taken from:
//https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
WriteFile(hFile, "RIFF", 4, &bytesWritten, NULL);
dwReturn = 36 + waveHeader.dwBytesRecorded * waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
WriteFile(hFile, &dwReturn, 4, &bytesWritten, NULL);
WriteFile(hFile, "WAVE", 4, &bytesWritten, NULL);
WriteFile(hFile, "fmt ", 4, &bytesWritten, NULL);
dwReturn = 16;
WriteFile(hFile, &dwReturn, 4, &bytesWritten, NULL);
WriteFile(hFile, &waveFormat.wFormatTag, 2, &bytesWritten, NULL);
WriteFile(hFile, &waveFormat.nChannels, 2, &bytesWritten, NULL);
WriteFile(hFile, &waveFormat.nSamplesPerSec, 4, &bytesWritten, NULL);
dwReturn = waveFormat.nSamplesPerSec * waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
WriteFile(hFile, &dwReturn, 4, &bytesWritten, NULL);
dwReturn = waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
WriteFile(hFile, &dwReturn, 2, &bytesWritten, NULL);
WriteFile(hFile, &waveFormat.wBitsPerSample, 2, &bytesWritten, NULL);
WriteFile(hFile, "data", 4, &bytesWritten, NULL);
//dwReturn = waveHeader.dwBytesRecorded * waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
WriteFile(hFile, &waveHeader.dwBytesRecorded, 4, &bytesWritten, NULL);
WriteFile(hFile, waveHeader.lpData, waveHeader.dwBytesRecorded, &bytesWritten, NULL);
CloseHandle(hFile);
waveInUnprepareHeader(hWaveIn, &waveHeader, sizeof(waveHeader));
delete[] waveHeader.lpData;
waveInClose(hWaveIn);
return ERROR_SUCCESS;
}
BOOL Play()
{
DWORD dwReturn;
HWAVEOUT hWaveOut;
WAVEHDR waveHeader;
WAVEFORMATEX waveFormat = {
WAVE_FORMAT_PCM, //wFormatTag;
1, //nChannels;
11025, //nSamplesPerSec;
11025, //nAvgBytesPerSec;
1, //nBlockAlign;
8, //wBitsPerSample,
0 };
HANDLE hFile = CreateFile(TEXT("recording.wav"), GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
dwReturn = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, NULL, NULL, CALLBACK_NULL);
if (dwReturn != ERROR_SUCCESS)
{
Error("waveOutOpen", dwReturn);
return dwReturn;
}
waveOutSetVolume(hWaveOut, 0xFFFF);
waveHeader.dwFlags = 0;
waveHeader.dwBufferLength = BUFFER_SIZE;
waveHeader.lpData = new char[waveHeader.dwBufferLength];
SetFilePointer(hFile, 44, 0, SEEK_SET); //data
ReadFile(hFile, waveHeader.lpData, waveHeader.dwBufferLength, &dwReturn, NULL);
CloseHandle(hFile);
dwReturn = waveOutPrepareHeader(hWaveOut, &waveHeader, sizeof(waveHeader));
if (dwReturn != ERROR_SUCCESS)
{
Error("waveOutPrepareHeader", dwReturn);
return dwReturn;
}
dwReturn = waveOutWrite(hWaveOut, &waveHeader, sizeof(waveHeader));
if (dwReturn != ERROR_SUCCESS)
{
Error("waveOutWrite", dwReturn);
return dwReturn;
}
waveOutUnprepareHeader(hWaveOut, &waveHeader, sizeof(waveHeader));
delete[] waveHeader.lpData;
while ((waveHeader.dwFlags & WHDR_DONE) != WHDR_DONE);
waveOutClose(hWaveOut);
return ERROR_SUCCESS;
}
int main()
{
Record(/*15000*/);
//Play();
printf("Done!\n");
return 0;
} |
Needs a little cleaning and improvment, but after I'll get it working.
The Record function works fine. it's the Play function that's giving me a hard time. I just have no idea what is it that I do wrong?
I thought maybe the input wasn't good or in the correct format, so I've created a WAV file by adding a few lines of code quickly but it seems to work when I play it using a media player.
I also tried adjusting the volume with code, double checked for errors, nothing.
Last edited by Deltron Z on Tue Oct 12, 2010 10:35 am; edited 2 times in total |
|
Back to top |
|
 |
HomerSexual Grandmaster Cheater Supreme
Reputation: 5
Joined: 03 Feb 2007 Posts: 1657
|
Posted: Mon Oct 11, 2010 11:13 pm Post subject: |
|
|
if this were in java i'd help you since i just wrote a program to do that! I don't know how in C++
in java it's basically
1. get handle to mic mixer from system
2. define targetdataline and crap like that
3. record until line is empty (which it will never be so you have a stop/start button)
4. write all that to a buffer which can be used for playback, writing audio file, etc
_________________
|
|
Back to top |
|
 |
Deltron Z Expert Cheater
Reputation: 1
Joined: 14 Jun 2009 Posts: 164
|
Posted: Tue Oct 12, 2010 10:29 am Post subject: |
|
|
Thanks for trying to help, but it sounds very different from the APIs I have.
I don't really write in Java, I guess I wouldn't have any problems writing in it, but I just want to learn about these APIs before using a higher level language such as Java or C# which probably contains a set of classes ready for use.
I just wonder why recording works perfectly fine but playing it doesn't work. the only thing I can think of is that I passed wrong parameters or needed a call to some other API first, because the documentation isn't very helpful.
Edit:
Oh man... I wrote better things drunk... this is the last time I'm writing stuff at 5:00 AM!
I deleted the buffer and used Unprepare Header BEFORE I let the buffer play... I just moved the loop before that.
Who am I kidding, you always write the best codes at night!
Now it's like this:
Code: | DWORD Play()
{
DWORD dwReturn;
HWAVEOUT hWaveOut;
WAVEHDR waveHeader;
WAVEFORMATEX waveFormat = {
WAVE_FORMAT_PCM, //wFormatTag;
1, //nChannels;
11025, //nSamplesPerSec;
11025, //nAvgBytesPerSec;
1, //nBlockAlign;
8, //wBitsPerSample,
0 };
HANDLE hFile = CreateFile(TEXT("C:\\recording.wav"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return (DWORD)INVALID_HANDLE_VALUE;
dwReturn = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, NULL, NULL, CALLBACK_NULL);
if (dwReturn != ERROR_SUCCESS)
{
Error("waveOutOpen", dwReturn);
return dwReturn;
}
//waveOutSetVolume(hWaveOut, 0xFFFF);
waveHeader.dwFlags = 0;
waveHeader.dwBufferLength = BUFFER_SIZE;
waveHeader.lpData = new char[waveHeader.dwBufferLength];
SetFilePointer(hFile, 44, 0, SEEK_SET); //data
ReadFile(hFile, waveHeader.lpData, waveHeader.dwBufferLength, &dwReturn, NULL);
CloseHandle(hFile);
dwReturn = waveOutPrepareHeader(hWaveOut, &waveHeader, sizeof(waveHeader));
if (dwReturn != ERROR_SUCCESS)
{
Error("waveOutPrepareHeader", dwReturn);
return dwReturn;
}
dwReturn = waveOutWrite(hWaveOut, &waveHeader, sizeof(waveHeader));
if (dwReturn != ERROR_SUCCESS)
{
Error("waveOutWrite", dwReturn);
return dwReturn;
}
do
Sleep(100);
while ((waveHeader.dwFlags & WHDR_DONE) != WHDR_DONE);
waveOutUnprepareHeader(hWaveOut, &waveHeader, sizeof(waveHeader));
delete[] waveHeader.lpData;
waveOutClose(hWaveOut);
return ERROR_SUCCESS;
} |
Notice I've changed the return value, because it used to return BOOL but I returned ERROR_SUCCESS which is 0 which is FALSE.
Now I'm returning (DWORD)-1 when hFile == INVALID_HANDLE_VALUE and the last error when another error has occurred.
|
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|