Link to home
Start Free TrialLog in
Avatar of renam00
renam00

asked on

I want save data from LPVOID* to a file

Hi
I gess this one is easy but you know...
I'm using VC++.
I building a resource DLL. I've put a WAV file in it. I want to (when the dll is loaded) save this wav in a file in order to play it.
With the [Find | Load | Lock | Sizeof]Resource I got a LPVOID pointer to my dll data.
(now the question...)
How can I transform this data into a file ?
Here what I have tried :

ofstream  f("CreatedFile.wav", ios::out)
// I have also tried with ios::binary...
LPVOID pWav; //then I do the "stuff"
BYTE* tab = (BYTE *) pWav;
for (i = 0; i < sor; i++)
   f << tab[i];

The file I obtain with this is not to good size and do not contains "wav data".

I you think I should know something about getting the pointer to the wav, feel free to tell me.

Thanks

renam00
Avatar of Gandalf32
Gandalf32

instead of using an ofstream, you could use a CFile (if using MFC) or call OpenFile()

Then simply call (if using MFC)
Write(pWav, sor);

or:
Write(hFile, pWav, sor);
Avatar of jkr
Try

ofstream  f("CreatedFile.wav", ios::binary)

f.write ( ( unsigned char*) pWav, sor);
The following is a function I use for my screen saver installation program. Modify it as needed.

BOOL CSInstallApp::SaveResourceToFile(LPCTSTR lpszSavePath, LPCTSTR lpszRes) const
{
    ASSERT(lpszSavePath != NULL);
    ASSERT(::AfxIsValidString(lpszSavePath));

    HRSRC hRsrc = ::FindResource(::AfxGetResourceHandle(), lpszRes, RT_RCDATA);
    if (hRsrc == NULL)
        return FALSE;

    DWORD dwSize = ::SizeofResource(::AfxGetResourceHandle(), hRsrc);
    HGLOBAL hResData = ::LoadResource(::AfxGetResourceHandle(), hRsrc);
    LPVOID lpData = ::LockResource(hResData);

    if (lpData == NULL)
        return FALSE;

    try
    {
        CFile file(lpszSavePath,
                   CFile::modeCreate | CFile::modeWrite |
                   CFile::shareExclusive);
        file.Write(lpData, dwSize);
    }
    catch (CFileException *pEx)
    {
        pEx->Delete();

        return FALSE;
    }

    return TRUE;
}
Fist off, I couldn't find any mention of audio resources in the online. Secondly, the layout of the the resource in memory is probably different from the layout in a disk based file. Bitmaps for instance, should have additional information when stored on disk. Secondly the online has a nasty remark with LockResource:
"Trying to lock a resource by using the handle returned by the FindResource or FindResourceEx function will not work. You will get back a value that is incorrect and points to random data."
If You want  not use MFC try with

FILE* file = fopen("CreatedFile.wav", "w");
fwrite(pWav, sor, sor, file);

You have not need of cast.
>I couldn't find any mention of audio resources in the online.

Playing WAVE Resources
http://msdn.microsoft.com/isapi/msdnlib.idc?theURL=/library/psdk/multimed/wave_3cfo.htm

>the layout of the the resource in memory is probably different from the layout in a disk based file.

The data keeps intact.

>the online has a nasty remark with LockResource "...".

What's wrong?
Of course if you lock a resource using a handle returned by FindResource you will get into trouble. That's what the LoadResource function is for, to load the resource in memory. That is the handle that nust be used.
Avatar of renam00

ASKER

Thanks to everybody but...
I've tried (and re-tried) all of your solutions (exept the MFC-ones, but I think I'll have to try those too...) and  I still have an non-audio-wrong-file-size file.
I'll do more test monday with the CFile.

tanks

renam00
PIG> If You want  not use MFC try with

 PIG> FILE* file = fopen("CreatedFile.wav", "w");
 PIG> fwrite(pWav, sor, sor, file);  

Er, you want that to be "wb" and not "w", because a WAV file certainly has binary data in it, and shouldn't have cr/lf translation!

 renam00>  I still have an non-audio-wrong-file-size file.

What, specifically, is wrong with the file?  Too long?  Too short? By how many bytes?  What does it look like when you dump it?

..B ekiM
 
>> The data keeps intact.
Try it with bitmaps :)

If a file header is required, the data may be intact but in the wrong place in the file.
Avatar of renam00

ASKER

The file I use for my tests is : "The Microsoft Sound.wav" i.e. 135 876 Kb. The file I get is 102 016 Kb (and do not play). I get this with those instr.:

ofstream  f("CrFile.wav", ios::binary);
char* tab = (BYTE *) pWav;
for (i = 0; i < sor; i++)
  f << tab[i];

And with these one :
FILE* file = fopen("CrFile.wav", "bw");
fwrite(pWav, sor, sor, file);
fclose(file);              
I get a 0kb file ! (with "bw", "wb" and "w");

Of course, I get the "pWav" from LockResource (and not from the LoadResouce ... btw those are exacly the same pointer (!?))

I begin to think I can't do this in a simple way, what about you ?

renam00
It is work in app. If You pass instead NULL handle of Your DLL ithink that You have not a problem.

hrsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_WAV),"WAV");
hgb = (HGLOBAL)LoadResource(NULL,hrsrc);
size  = SizeofResource(NULL,hrsrc);
char* bufHGB = new char[size + 1];
memset(bufHGB, 0 , size + 1);
memcpy(bufHGB,(char*)LockResource(hgb),size);
UnlockResource(hgb);
FreeResource(hgb);
FILE* file = fopen("CreatedFile.wav", "w");
fwrite(bufHGB, size, size, file);
fclose(file);
ShellExecute(mHWND, "open", "CreatedFile.wav", NULL, ".\", SW_SHOWNORMAL);

 
The file I use for my tests is : "The Microsoft Sound.wav"

 > i.e. 135 876 Kb. The file I get is 102 016 Kb
 > (and do not play). I get this with those instr.:

Certainly, you must mean "b" and not "Kb", right? A file that's 135876 Kilobytes in size is very, very large! Presumably, you've checked in the debugger to make sure that sor shows 135876 bytes, right?

 > And with these one :
 > FILE* file = fopen("CrFile.wav", "bw");

This should be "wb", not "bw".

 > fwrite(pWav, sor, sor, file);

Wrong!  You need to code

   fwrite(pWav, 1, sor, file);

 > fclose(file);                
 > I get a 0kb file ! (with "bw", "wb" and "w");  

Please use "wb".


 > ofstream  f("CrFile.wav", ios::binary);
 > char* tab = (BYTE *) pWav;
 >for (i = 0; i < sor; i++)
     f << tab[i];

It's a mystery to me why you wouldn't use ofstream's write method, here. What you're doing is wrong and inefficient. Instead of that loop, you should code:

      f.write(pWav, sor);

..B ekiM


 
PIG> memset(bufHGB, 0 , size + 1);

There's absolutely no reason to make this call.

 PIG> fwrite(bufHGB, size, size, file);

Wow, PIG!  You made the exact same mistake as the person asking the question! This call causes you to write a file that's size*size bytes long; if the starting file is 135000 bytes, the file you're trying to write will be 18225000000 bytes in size. That's waaay too big!

Fortunately, fwrite() will cause an access violation before it writes a file that big, but...

..B ekiM
I am sorry it is cut/paste misake. But iti is work. Believe me!:-(
Are you sure the data contained in the resource is correct. Maybe you are working with corrupt data to begin with.
> Maybe you are working with corrupt data to begin with.

Right. That's why we need to find out what's in the "sor" variable.

..B ekiM
Avatar of renam00

ASKER

Ok, you're right the file size I gave you is in byte...

The line : f.write(pWav, sor);
 
give me this error :
error C2664: 'class ostream &__thiscall ostream::write(const char *,int)' : cannot convert parameter 1 from 'void *' to 'const char *'
        Conversion from 'void*' to pointer to non-'void' requires an explicit cast

So I do the mandatory cast :
 f.write((char*)pWav, sor);
And I get a 96 920 byte file.
The file "f" is open with ios::binary.

The resource I'm (trying to) exporting is the right (sor is exacly the size of the original file in byte). And When I export the file from VisualStudio, I get exacly the file I want to...So the're must be a way.

Thanks, renam00

Avatar of renam00

ASKER

Guys, I understand I take lots of your time. So in a very generous move, I'm increasing the points to 150 !
Avatar of renam00

ASKER

Adjusted points to 150
Try if this works:

hrsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_WAV),"WAV");
hgb = (HGLOBAL)LoadResource(NULL,hrsrc);
int nSizeTest;
size  = SizeofResource(NULL,hrsrc);
HANDLE hFile = CreateFile("CreatedFile.wav", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
WriteFile(hFile, LockResource(hgb), size, &nSizeTest, NULL);
CloseHandle(hFile);
UnlockResource(hgb);
FreeResource(hgb);
ShellExecute(mHWND, "open", "CreatedFile.wav", NULL, ".\", SW_SHOWNORMAL);

You can compare nSizeTest to size and see if the bytes written are the same as the total bytes.
What's really the problem? You can also play a Soundfile which is placed in a dll or exe as resource without saving it in a wave-file. You can do it this way:
PlaySound(MAKEINTRESOURCE(MY_WAVE),NULL,SND_RESOURCE|SND_SYNC);

That's it. You just have to add #include <mmsystem.h>
and add winmm.lib to the linking options. The resource has to be from the type "WAVE" and the identifier is MY_WAVE. If you want to play the sound from a dll, which you load by LoadLibrary you can use the HMODULE handle you get instead of NULL in PlaySound.

I hope I could help you.
Avatar of renam00

ASKER

I'm pretty sure this is working fine, however It's not what's I'm looking for. Moreover I begin to take this problem "personal"... I can't believe it's that hard to save data to a file when I have a pointer to the data chunk !

renam
ASKER CERTIFIED SOLUTION
Avatar of mikeblas
mikeblas

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
There are a number of assumptions in the procedure:

1. There is an object which can be considered as a pointer to some chunk of (wave) data
2. The size of this chunk is known
3. The layout of this chunk is identical to the layout of a WAV file

First of all, check the file that is written. Look at the file sizes, look with a hex viewer and compare it to the original (working) wave file. See if you can get any clues from this.
We know that all three assumptions are true because renam00 told us so--he added a WAV file to the resources of his DLL.

Data doesn't change format when it ends up in a resource. And, so, writing the resource out to a file, byte-by-byte, is just fine for this case.

..B ekiM
Avatar of renam00

ASKER

Mike , the description of the program WRITERES seems exacly what I<m looking for but the file is not there. (neiter at mooseboy.com) ... I'll try again later.
renam
OOps!  Fixed it.

..B ekiM
Avatar of renam00

ASKER

This is exacly what I was looking for ! I think the proplem that I have came from my LockRessource. I pass by a LPVOID and then I cast it to a BYTE*.
Anyway thanks a lot (and I'll bookmark your pages for further help...)
I'll give you the points by thank also to everybody who tried to help me.

renam