So to give a quick synopsis of how my engine handles wave files loaded from disk.
1. Create a DMusic segment using the Loader method LoadObjectFromFile()
2. Download the segment to the performance object and store a pointer to the segment in my wrapper class.
3. When I shut down I unload the segments and then release them.
My assumption of what was happening was that the segment was a chunk of memory that gets allocated upon creation and the gets deallocated upon release. Because after all I'm not passing it a buffer nor do I get a buffer back.
So I went about doing a similar thing when loading wave files from memory.
1. Load the data into a freshly allocated memory buffer.
2. Create a DMusic segment using the Loader method GetObject().
3. Delete the buffer since I assumed that the segment now had a copy of the data.
4. Download the segment to the performance object and store a pointer to the segment in my wrapper class.
5. When I shut down I unload the segments and then release them.
Of course my assumptions were incorrect and somewhere behind the scenes LoadObjectFromFile() creates a buffer somewhere that the segment points to and isn't actually part of the segment. I'm not sure how it gets cleaned up on shutdown but it must.
So when I cleared my buffer in step #3 above my segment was now pointing to what was basically a random chunk of memory. It's amazing that I had any sound working at all but such is the magic of memory allocations.
What made me take so long in getting down to the final solution is that the only example usage of GetObject() that I could find loaded data from a resource using LoadResource() and not just a byte buffer. It ends up that LoadResource() handles magic buffers for you automatically.
So what have I learned from all this wasted time? Don't assume that you know what's going on in a black box!!! And next time when debugging something that might be a weird memory bug comment out the deallocation steps and see if that fixes things. It's ok to leak memory to test out a theory!!!