ASCII to .wav
-
Wednesday, September 19, 2012 7:59 PM
Hi,
I am working on a software that can process .wav files. And I need to modify it so that it can process ASCII files too. I am considering converting ASCII files to .wav files so it can be processed. Please kindly help me if you have any advice.
All Replies
-
Wednesday, September 19, 2012 10:54 PMModerator
What does your software do with the .wav file or ASCII file?
Matthew van Eerde
-
Thursday, September 20, 2012 3:54 PMModerator
I'm trying to make sure I understand your scenario so I give you the right recommendation.
Are you trying to change a text file (something like this...)
Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that...
... into an audio file (something like this?)
If so you want a text-to-speech solution.
Windows comes with a text-to-speech solution, which empowers the Narrator feature that reads the contents of the screen to you. It also comes with a speech-to-text solution, which empowers the Speech Recognition feature that allows you to give voice commands to the computer.
You can read about Windows' text-to-speech APIs here:
http://msdn.microsoft.com/en-us/library/ms720570(v=vs.85).aspx
Matthew van Eerde
-
Thursday, September 20, 2012 4:52 PMModerator
Here's a quick sample of how to use the Windows ISpVoice text-to-speech APIs.
More thorough samples exist in the Windows SDK. See http://msdn.microsoft.com/en-us/library/ms720406(v=vs.85).aspx
Matthew van Eerde
-
Thursday, September 20, 2012 7:50 PM
Hi Matthew,
Thank you for your warmhearted reply first.
My software is a Matching Pursuit software that reads and processes .wav files (decompose, reconstruct etc.). My task is to make it able to read and process ASCII files. So I am considering how to write a piece of code to convert ASCII files to .wav files using C++ in Microsoft Visual Studio 2010.
As for ASCII files, I do not think it is like the example you gave about the Gettysburg Speech. It should be series of letters or numbers which captures the essence of a signal. And I am trying to convert ASCII files to .wav files because the current software can process only .wav files.
In sum, I just wanna make the software able to read and process ASCII files. And the method above is what comes to mind mind on how to realize it. (Though There may be other better ways, if you know, you can teach me probably).
Thanks a lot~
-
Thursday, September 20, 2012 8:26 PMModeratorCan you give me an example of an ASCII file which is a series of letters or numbers which captures the essence of a signal? You can upload it somewhere and post a link, or you can send it to me at (mateer at microsoft dot com)
Matthew van Eerde
-
Thursday, September 20, 2012 8:42 PMModeratorIf you're looking to generate a signal based on a given formula, you can use mmioWrite to create a .wav file from generated data. See http://blogs.msdn.com/b/matthew_van_eerde/archive/2008/12/16/sample-wasapi-loopback-capture-record-what-you-hear.aspx for an example of how to use the mmio APIs.
Matthew van Eerde
-
Friday, September 21, 2012 4:33 PM
Hi Matthew,
I would say that if we use wavread(***.wav) in matlab, we get the ascii file of that .wav file.
-
Friday, September 21, 2012 5:07 PMModerator
I see; you have a bunch of raw sample values (a big array of numbers) and you want to write them to a .wav file, something like Matlab's wavwrite(...) function.
mmioOpen / mmioWrite is a good fit for this, so the loopback-capture sample above should help.
Internally, .wav files are a RIFF file with three important chunks:
- The RIFF/WAVE chunk
- The "fmt " chunk (note the space) which says what format the audio data is in
- The "data" chunk which contains the actual audio data
Each chunk has a header and a body. The header says what type of chunk it is, and how big the chunk is: in the case of the RIFF/WAVE chunk this is the eight bytes 'R', 'I', 'F', 'F', 'W', 'A', 'V', 'E' plus a four-byte integer which is the size of the file not counting these twelve bytes. In the case of the "fmt " chunk this is the four bytes 'f', 'm', 't', ' ' plus a four-byte integer which is the size of the format not counting these eight bytes, in WAVEFORMATEX form. In the case of the "data" chunk this is the four bytes 'd', 'a', 't', 'a' plus a four-byte integer which is the size of the audio data not counting these four bytes.
So here's how you write the header:
MMIOINFO mi = {0};
HMMIO hFile = nullptr;
hFile = mmioOpen(
// some flags cause mmioOpen write to this buffer
// but not any that we're using
const_cast<LPWSTR>(szFileName),
&mi,
MMIO_WRITE | MMIO_CREATE
);MMCKINFO ckRIFF = {0};
// make a RIFF/WAVE chunk
ckRIFF.ckid = MAKEFOURCC('R', 'I', 'F', 'F');
ckRIFF.fccType = MAKEFOURCC('W', 'A', 'V', 'E');mmr = mmioCreateChunk(hFile, &ckRIFF, MMIO_CREATERIFF);
if (MMSYSERR_NOERROR != mmr) {
printf("mmioCreateChunk(\"RIFF/WAVE\") failed: MMRESULT = 0x%08x\n", mmr);
return E_FAIL;
}// make a 'fmt ' chunk (within the RIFF/WAVE chunk)
MMCKINFO chunk;
chunk.ckid = MAKEFOURCC('f', 'm', 't', ' ');
mmr = mmioCreateChunk(hFile, &chunk, 0);
if (MMSYSERR_NOERROR != mmr) {
printf("mmioCreateChunk(\"fmt \") failed: MMRESULT = 0x%08x\n", mmr);
return E_FAIL;
}// write the WAVEFORMATEX data to it
WAVEFORMATEX wfx = (your format here, which may need to be a WAVEFORMATEXTENSIBLE);
LONG lBytesInWfx = sizeof(WAVEFORMATEX) + wfx.cbSize;
LONG lBytesWritten =
mmioWrite(
hFile,
reinterpret_cast<PCHAR>(&wfx),
lBytesInWfx
);
if (lBytesWritten != lBytesInWfx) {
printf("mmioWrite(fmt data) wrote %u bytes; expected %u bytes\n", lBytesWritten, lBytesInWfx);
return E_FAIL;
}// ascend from the 'fmt ' chunk
mmr = mmioAscend(hFile, &chunk, 0);
if (MMSYSERR_NOERROR != mmr) {
printf("mmioAscend(\"fmt \" failed: MMRESULT = 0x%08x\n", mmr);
return E_FAIL;
}
// make a 'data' chunk and leave the data pointer there
MMCKINF ckData = {0};
ckData.ckid = MAKEFOURCC('d', 'a', 't', 'a');
mmr = mmioCreateChunk(hFile, &ckData, 0);
if (MMSYSERR_NOERROR != mmr) {
printf("mmioCreateChunk(\"data\") failed: MMRESULT = 0x%08x\n", mmr);
return E_FAIL;
}And here's where you write the data:
// here you write your sample values
PCHAR pData = (your data here);
LONG lBytesToWrite = (length of your data in bytes);
LONG lBytesWritten = mmioWrite(hFile, pData, lBytesToWrite);
if (lBytesToWrite != lBytesWritten) {
printf("mmioWrite wrote %u bytes: expected %u bytes\n", lBytesWritten, lBytesToWrite);
}And here's how you clean up. mmioAscend automatically fills in the sizes of the chunks you've just finalized.
// ascend from the data chunk
mmr = mmioAscend(hFile, &ckData, 0);
if (MMSYSERR_NOERROR != mmr) {
printf("mmioAscend(\"data\" failed: MMRESULT = 0x%08x\n", mmr);
return E_FAIL;
}// ascend from the RIFF chunk
mmr = mmioAscend(hFile, &ckRIFF, 0);
if (MMSYSERR_NOERROR != mmr) {
printf("mmioAscend(\"RIFF/WAVE\" failed: MMRESULT = 0x%08x\n", mmr);
return E_FAIL;
}// close the file
mmioClose(m_hFile, 0);In addition to the raw data you will need to provide a description of what format the audio data is in. Are they four-byte floating-point IEEE values? Or are they sixteen-bit signed integers? How many channels are there (mono? stereo? 5.1?) How frequently was the data sampled?
For example, if you were using stereo sixteen-bit signed integers, sampled 44100 times per second, you would fill out the WAVEFORMATEX as follows:
wfx.wFormatTag = WAVE_FORMAT_PCM; // WAVE_FORMAT_PCM is integer; WAVE_FORMAT_IEEE_FLOAT is float
wfx.nChannels = 2; // stereo; left and right channels
wfx.nSamplesPerSec = 44100;
wfx.wBitsPerSample = 16; // two bytes for each number; 8-bit is implicitly unsigned, all else are signed// these can be calculated from the data above
wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; // number of bytes for a single audio frame
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;// some formats (e.g. WAVEFORMATEXTENSIBLE) are bigger
// this is the number of bytes in the format beyond the WAVEFORMATEX structure
// the total size is sizeof(WAVEFORMATEX) + wfx.cbSize
wfx.cbSize = 0;
Matthew van Eerde
- Edited by Maurits [MSFT]Microsoft Employee, Moderator Friday, September 21, 2012 5:09 PM
- Edited by Maurits [MSFT]Microsoft Employee, Moderator Friday, September 21, 2012 5:10 PM
- Marked As Answer by Daniel Lee 123456 Friday, September 21, 2012 7:17 PM
-
Friday, September 21, 2012 7:21 PM
Hi Matthew,
thank for your answers. I am not sure whether it works for that. But I am told that during the process of converting ASCII files to .wav files some information will be lost... Therefore, I have to write code to directly read and process ASCII files. But thanks for your help, anyways.


