Embarcadero CoCreateInstance exception 0x40000015

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

hi guys, i don't understand why if the midi interface is open and i call

Code: Select all

IMMDeviceEnumerator * deviceEnumerator;
hr = CoCreateInstance (__uuidof(MMDeviceEnumerator), 
                                   NULL, 
                                   CLSCTX_ALL,
                                   __uuidof (IMMDeviceEnumerator), 
                                   (LPVOID *)(&deviceEnumerator));
assert (hr == S_OK);
I get an exception 0x40000015. If I don't open the midi interface, everything is ok.

Thanks
HsiaLin
BCBJ Master
BCBJ Master
Posts: 343
Joined: Sun Jul 08, 2007 6:29 pm

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by HsiaLin »

Been years since i worked with COM but you may need to add

CoInitialize(NULL);

at the top of the code
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

thanks HsiaLin, now it works.
rlebeau
BCBJ Author
BCBJ Author
Posts: 1759
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by rlebeau »

mark_c wrote: Sun Dec 27, 2020 6:19 am I get an exception 0x40000015
Exception code 0x40000015 is STATUS_FATAL_APP_EXIT. Is your app actually exiting due to an uncaught exception? Does the exception happen on the call to CoCreateInstance() itself, or on the assert()? If you hadn't called CoInitialize/Ex() yet before calling CoCreateInstance(), I would have expected CoCreateInstance() to fail * with an HRESULT of CO_E_NOT­INITIALIZED (0x800401F0), which would then cause the subsequent assert() to fail.

* See Why does CoCreateInstance work even though my thread never called CoInitialize? The curse of the implicit MTA
Last edited by rlebeau on Tue Dec 29, 2020 3:58 pm, edited 1 time in total.
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

maybe you can give me a tip here too, although it's not a development environment problem.
In summary my code for playing a buffer in wav format is this. I send a buffer of wav samples and it plays regularly. The problem is that if I keep sending buffers, when I get to about 400 sends I still have exception 0x40000015 due to the fact that it is not clear how and when to use Stop () and Release ().
If he is called immediately there is no sound. If I use Sleep () it is not possible to overlap the sounds as the next sound queues to the previous one.
If I delete Sleep () Stop () and Release () the program behaves as I want (the sounds are mixed) but I have an exception after about 400 sends.
Do you have a tip for me?

Code: Select all

void PlayBufferWasapi(short *fileBytes, int fileSize)
{
	CoInitialize(NULL);

	hr = CoCreateInstance();

	deviceEnumerator->GetDefaultAudioEndpoint();
	deviceEnumerator->Release();

	hr = audioDevice->Activate();
	audioDevice->Release();

	WAVEFORMATEX wfx = {WAVE_FORMAT_PCM, 2 44100, 16, 4, 176200};

	audioClient->Initialize();

	audioClient->GetService();
	
	audioClient->GetBufferSize();
	
	audioClient->Start();
	
	audioClient->GetCurrentPadding();

	audioRenderClient->GetBuffer();

	audioRenderClient->ReleaseBuffer();

	/*
	Sleep(time_play * 1000);

	audioClient->Stop();
	audioClient->Release();
	audioRenderClient->Release();
	*/
}
rlebeau
BCBJ Author
BCBJ Author
Posts: 1759
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by rlebeau »

mark_c wrote: Tue Dec 29, 2020 2:42 am maybe you can give me a tip here too, although it's not a development environment problem.
Well, for starters, CoInitalize() does not belong inside of PlayBufferWasapi() itself. It belongs at the start of any threads that are calling PlayBufferWasapi(). COM needs to be initialized only once per-thread, not per-function.
mark_c wrote: Tue Dec 29, 2020 2:42 am In summary my code for playing a buffer in wav format is this. I send a buffer of wav samples and it plays regularly. The problem is that if I keep sending buffers, when I get to about 400 sends I still have exception 0x40000015 due to the fact that it is not clear how and when to use Stop () and Release ().
You didn't answer my earlier question about that exception. What you just described still implies to me that you are likely not handling COM errors correctly, causing side-effects in other code that ultimately results in your app terminating itself. There is no error handling present in the code you have shown.
mark_c wrote: Tue Dec 29, 2020 2:42 am If he is called immediately there is no sound. If I use Sleep () it is not possible to overlap the sounds as the next sound queues to the previous one.
If I delete Sleep () Stop () and Release () the program behaves as I want (the sounds are mixed) but I have an exception after about 400 sends.
Do you have a tip for me?
Yeah - stop ignoring errors. Beyond that, I can't really help you, as I'm not a multimedia developer. It sounds like maybe you are simply queuing up more buffers than the audio device can handle. Does the API give you any kind of feedback about that? An error code when the queue is full, or events when buffers are removed from the queue? Anything you can use to throttle your pushing of buffers with?
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

you're right Remy, I'm absolutely not handling the errors. Beyond this aspect that you emphasize and which is very important, it seems that this is also a problem similar to that of sockets that you explained to me some time ago.

Practically:
- always ask how much free space there is in the wasapi buffer
- if there is no space wait a few ms
- count how many bytes you have already sent to the wasapi buffer
- when your buffer is zero stop the loop

I also have no experience in multimedia programming, it is my first project of this type. Unfortunately I find few suggestions on how to solve doubts and problems.

Thanks anyway
HsiaLin
BCBJ Master
BCBJ Master
Posts: 343
Joined: Sun Jul 08, 2007 6:29 pm

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by HsiaLin »

You only need to call CoInitialize(NULL); once, like when your form loads the
first time...as long as you have not called CoUninitilize(); it should stay ok.

You probably should call CoUninitialize(); as your program closes.
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

thanks HsiaLin, my fault.
I'm not writing a music file player but a player for musicians.
To make you understand: I have implemented a part that by pressing one or more keys of the keyboard you can play chords like a piano.
For example, if I press three keys together, I get a chord and think that I don't have to do anything to get it.
The wasapi engine takes care of adding the three sounds; how it does I don't know, but it adds them up in real time.
There is a problem: if I continue to press keys on the keyboard, the memory continues to allocate itself and once arrived at a certain point, exception 0x40000015 appears.
This happens because I absolutely don't know when to free my memory. Sure there is a trick to keep track of buffers passed to wasapi but I don't know about it; unfortunately it is a new situation for me.
Usually those who develop file players, when the song ends, calls:
audioClient-> Stop ();
audioClient-> Release ();
audioRenderClient-> Release ();
I can't do it otherwise I cut off the sound.
HsiaLin
BCBJ Master
BCBJ Master
Posts: 343
Joined: Sun Jul 08, 2007 6:29 pm

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by HsiaLin »

This is a VC project but the code in the renderer.cpp might be informative.

https://hackaday.io/project/47195-examp ... or-windows
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

thanks HsiaLin, I try to study it.
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

I still try to ask a question even if it is not related to the development environment.

Every time I call this PlayBufferWasapi () function a number of objects are instantiated, right?

If I never call back:
audioClient-> Stop ();
audioClient-> Release ();
audioRenderClient-> Release ();
at some point I'll find my memory full of objects, so to speak, PlayBufferWasapi () right?
And maybe no longer referenced and therefore no longer eliminable.
Is there a way to keep track of these PlayBufferWasapi () objects in order to free the memory after a certain amount of time?

Code: Select all

void PlayBufferWasapi(short *fileBytes, int fileSize)
{
	CoInitialize(NULL);

	hr = CoCreateInstance();

	deviceEnumerator->GetDefaultAudioEndpoint();
	deviceEnumerator->Release();

	hr = audioDevice->Activate();
	audioDevice->Release();

	WAVEFORMATEX wfx = {WAVE_FORMAT_PCM, 2 44100, 16, 4, 176200};

	audioClient->Initialize();

	audioClient->GetService();
	
	audioClient->GetBufferSize();
	
	audioClient->Start();
	
	audioClient->GetCurrentPadding();

	audioRenderClient->GetBuffer();

	audioRenderClient->ReleaseBuffer();

	/*
	Sleep(time_play * 1000);

	audioClient->Stop();
	audioClient->Release();
	audioRenderClient->Release();
	*/
}
rlebeau
BCBJ Author
BCBJ Author
Posts: 1759
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by rlebeau »

mark_c wrote: Sun Jan 03, 2021 6:16 am Every time I call this PlayBufferWasapi () function a number of objects are instantiated, right?
Yes.
mark_c wrote: Sun Jan 03, 2021 6:16 am If I never call back:
audioClient-> Stop ();
audioClient-> Release ();
audioRenderClient-> Release ();
at some point I'll find my memory full of objects, so to speak, PlayBufferWasapi () right?
Yes. COM interfaces are reference counted. When you obtain a COM interface, its refcount is incremented, and you must Release() it to decrement its refcount when you are done using it.
mark_c wrote: Sun Jan 03, 2021 6:16 am Is there a way to keep track of these PlayBufferWasapi () objects in order to free the memory after a certain amount of time?
In your example, they are just local variables, so there is no need to "keep track" of them, since they are being created and destroyed inside the same function.

But, if you needed to create the objects and hold on to them for awhile, destroying them after PlayBufferWasapi() has exited, then obviously you would have to store them somewhere else. In this case, in global variables, since PlayBufferWasapi() is not a member of a class. And you would have to call CoInitialize()/CoUninitialize() at a more global scope as well (ie, at program startup/cleanup), which you should be doing anyway as they don't belong inside of PlayBufferWasapi() to begin with.
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

thanks Remy
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: Embarcadero CoCreateInstance exception 0x40000015

Post by mark_c »

I ask for confirmation: I think I understand that the first and second solutions are equivalent and MyFunction () does not generate race conditions if I instantiate 1000 threads, right?

Thanks

first solution

Code: Select all

void __fastcall TMyThread :: Execute()
{
       for (int i = 0; i <100; i ++)
                    Label1-> Caption = IntoToStr (i);
}
second solution

Code: Select all

void __fastcall TMyThread :: Execute()
{
      MyFunction();
}


void MyFunction()
{
       for (int i = 0; i <100; i ++)
                    Label1-> Caption = IntoToStr (i);
}
Post Reply