Languages

Menu
Sites
Language
Audio output under Emulator

I have a native application which contains a class that implements IAudioOutEventListener.

My class's Create() method attempts to initialize the audio output by calling the Audio Output Construct() method, as follows ...

 

class SingleAudioOut : public Tizen::Media::IAudioOutEventListener
{
public:
    result Create(void);
    ...
    ...
 
private:
    AudioOut __audioOut;
    ...
    ...
};
 
result SingleAudioOut::Create(void)
{
        result ret = __audioOut.Construct(*this);
        ...
        ...
}

 

The call to Construct() returns 0xA0000780, which is E_INVALID_OPERATION.
 

Is audio output from a Native Application supported under the emulator ?

If so, any suggestions as to what I am doing wrong ?

 

Edited by: Brock Boland on 17 Mar, 2014 Reason: Paragraph tags added automatically from tizen_format_fix module.

Responses

5 Replies
Ollanketo
I'm using AudioOut in my application, and have not had any problems running it in the emulator when using SDK versions 2.1 and 2.2beta. I haven't been able to test in 2.2 because of other problems. I'm assuming that you've implemented all the callbacks of IAudioOutEventListener, even if only as a bunch of empty methods(?).
Kevin Raine
Thanks for your reply. It fails for me under Tizen SDK 2.1 and 2.2. I am currently using SDK 2.2. Please correct me if I'm wrong, but I believe have implemented the required methods (see below) ... class SingleAudioOut : public Tizen::Media::IAudioOutEventListener { public: result Create(void); void Destroy(void); result Start(void); void SubmitBuffer(void); void Pause(void); void Resume(void); virtual void OnAudioOutBufferEndReached(Tizen::Media::AudioOut& src); virtual void OnAudioOutErrorOccurred(Tizen::Media::AudioOut& src, result r) {} virtual void OnAudioOutInterrupted(Tizen::Media::AudioOut& src) {} virtual void OnAudioOutReleased(Tizen::Media::AudioOut& src) {} virtual void OnAudioOutAudioFocusChanged(Tizen::Media::AudioOut& src) {} private: AudioOut __audioOut; AudioSampleType format; AudioChannelType channels; AKDint frequency; int minBufferSize; AKDint numframes; int framelen; ByteBuffer __buffer[MAX_BUFFER_COUNT]; int __bufIndex; }; void SingleAudioOut::OnAudioOutBufferEndReached(Tizen::Media::AudioOut& src) { SubmitBuffer(); }
Ollanketo
Looks about right to me (I also leave all the callbacks empty except for OnAudioOutBufferEndReached). I implement IAudioOutEventListener as part of my ServiceApp, but I don't see how that would matter. The test machine I use is running Windows 7 64-bit, and I use the default emulator options (I might have had to enable virtualization myself with the 2.1 SDK, but that's it as far as I can recall). Anyway, here's a brief example that plays a square wave. It works fine for me using SDK 2.2: AudioOutTest.h
#ifndef _AUDIOOUTTEST_H_
#define _AUDIOOUTTEST_H_

#include <FApp.h>
#include <FBase.h>
#include <FMedia.h>
#include <FSystem.h>
#include <FUi.h>
#include <stdint.h>

/**
 * [AudioOutTest] UiApp must inherit from UiApp class
 * which provides basic features necessary to define an UiApp.
 */
class AudioOutTestApp
	: public Tizen::App::UiApp
	, public Tizen::System::IScreenEventListener
	, public Tizen::Media::IAudioOutEventListener
{
public:
	/**
	 * [Test] UiApp must have a factory method that creates an instance of itself.
	 */
	static Tizen::App::UiApp* CreateInstance(void);

public:
	AudioOutTestApp(void);
	virtual ~AudioOutTestApp(void);

public:
	// Called when the UiApp is initializing.
	virtual bool OnAppInitializing(Tizen::App::AppRegistry& appRegistry);

	// Called when the UiApp initializing is finished. 
	virtual bool OnAppInitialized(void); 

	// Called when the UiApp is requested to terminate. 
	virtual bool OnAppWillTerminate(void); 

	// Called when the UiApp is terminating.
	virtual bool OnAppTerminating(Tizen::App::AppRegistry& appRegistry, bool forcedTermination = false);

	// Called when the UiApp's frame moves to the top of the screen.
	virtual void OnForeground(void);

	// Called when this UiApp's frame is moved from top of the screen to the background.
	virtual void OnBackground(void);

	// Called when the system memory is not sufficient to run the UiApp any further.
	virtual void OnLowMemory(void);

	// Called when the battery level changes.
	virtual void OnBatteryLevelChanged(Tizen::System::BatteryLevel batteryLevel);

	// Called when the screen turns on.
	virtual void OnScreenOn(void);

	// Called when the screen turns off.
	virtual void OnScreenOff(void);

	void GenerateAudio(uint32_t numSamples, int16_t *buffer);

protected:
    virtual void OnAudioOutBufferEndReached(Tizen::Media::AudioOut& src);
    virtual void OnAudioOutErrorOccurred(Tizen::Media::AudioOut& src, result r) {}
    virtual void OnAudioOutInterrupted(Tizen::Media::AudioOut& src) {}
    virtual void OnAudioOutReleased(Tizen::Media::AudioOut& src) {}
    virtual void OnAudioOutAudioFocusChanged(Tizen::Media::AudioOut& src) {}
private:
    Tizen::Media::AudioOut mAudioOut;
    Tizen::Base::ByteBuffer mBuffers[2];
    int mCurPlayingBuffer;
    int mMinBufferSize;
    Tizen::Base::Runtime::Mutex mPlayerMutex;
};

#endif // _AUDIOOUTTEST_H_
AudioOutTest.cpp
/**
 * Name        : AudioOutTest
 * Version     : 
 * Vendor      : 
 * Description : 
 */


#include "AudioOutTest.h"
#include "AudioOutTestFrame.h"

using namespace Tizen::App;
using namespace Tizen::Base;
using namespace Tizen::Media;
using namespace Tizen::System;
using namespace Tizen::Ui;
using namespace Tizen::Ui::Controls;

int16_t phase = 0x3000;
uint32_t period = 100;


AudioOutTestApp::AudioOutTestApp(void)
{
}

AudioOutTestApp::~AudioOutTestApp(void)
{
}

UiApp*
AudioOutTestApp::CreateInstance(void)
{
	// Create the instance through the constructor.
	return new AudioOutTestApp();
}

bool
AudioOutTestApp::OnAppInitializing(AppRegistry& appRegistry)
{
	result r;

	// Create a Frame
	AudioOutTestFrame* pAudioOutTestFrame = new AudioOutTestFrame;
	pAudioOutTestFrame->Construct();
	pAudioOutTestFrame->SetName(L"AudioOutTest");
	AddFrame(*pAudioOutTestFrame);

	mPlayerMutex.Create();

    r = mAudioOut.Construct(*this);
    if (IsFailed(r)) {
    	AppLog("Failed to construct AudioOut");
        return false;
    }
    mAudioOut.Prepare(AUDIO_TYPE_PCM_S16_LE, AUDIO_CHANNEL_TYPE_STEREO, 44100);
    mMinBufferSize = mAudioOut.GetMinBufferSize() * 4;
    AppLog("Buffer size: %d bytes", mMinBufferSize);

    mBuffers[0].Construct(mMinBufferSize);
    mBuffers[1].Construct(mMinBufferSize);

    // Fill up both buffers with audio data and send the first one to the audio hw
	GenerateAudio(mMinBufferSize >> 2, (int16_t*)mBuffers[0].GetPointer());
	GenerateAudio(mMinBufferSize >> 2, (int16_t*)mBuffers[1].GetPointer());
	mAudioOut.WriteBuffer(mBuffers[0]);
	mCurPlayingBuffer = 0;

	if (IsFailed(mAudioOut.Start())) {
		AppLog("AudioOut::Start failed");
		return false;
    }

	return true;
}

void AudioOutTestApp::OnAudioOutBufferEndReached(Tizen::Media::AudioOut& src)
{
	mPlayerMutex.Acquire();

	// Switch buffers and fill up with new audio data
    mAudioOut.WriteBuffer(mBuffers[mCurPlayingBuffer ^ 1]);
    GenerateAudio(mMinBufferSize >> 2, (int16_t*)mBuffers[mCurPlayingBuffer].GetPointer());
    mCurPlayingBuffer ^= 1;

    mPlayerMutex.Release();
}


void AudioOutTestApp::GenerateAudio(uint32_t numSamples, int16_t *buffer)
{
	for (uint32_t i = 0; i < numSamples * 2; i += 2) {
		period--;
		if (!period) {
			period = 100;
			phase ^= 0x3000;
		}
		buffer[i] = buffer[i + 1] = phase;
	}
}


bool
AudioOutTestApp::OnAppInitialized(void)
{
	// TODO:
	// Comment.
	return true;
}

bool
AudioOutTestApp::OnAppWillTerminate(void)
{
	// TODO:
	// Deallocate or release resources that are UI dependent.
	return true;
}

bool
AudioOutTestApp::OnAppTerminating(AppRegistry& appRegistry, bool forcedTermination)
{
	mPlayerMutex.Acquire();

	mAudioOut.Stop();
	mAudioOut.Unprepare();

	mPlayerMutex.Release();

	return true;
}

void
AudioOutTestApp::OnForeground(void)
{
	// TODO:
	// Start or resume drawing when the application is moved to the foreground.
}

void
AudioOutTestApp::OnBackground(void)
{
	// TODO:
	// Stop drawing when the application is moved to the background.
}

void
AudioOutTestApp::OnLowMemory(void)
{
	// TODO:
	// Free unused resources or close the application.
}

void
AudioOutTestApp::OnBatteryLevelChanged(BatteryLevel batteryLevel)
{
	// TODO:
	// Handle any changes in battery level here.
	// Stop using multimedia features(camera, mp3 etc.) if the battery level is CRITICAL.
}

void
AudioOutTestApp::OnScreenOn(void)
{
	// TODO:
	// Get the released resources or resume the operations that were paused or stopped in OnScreenOff().
}

void
AudioOutTestApp::OnScreenOff(void)
{
	// TODO:
	// Unless there is a strong reason to do otherwise, release resources (such as 3D, media, and sensors) to allow the device
	// to enter the sleep mode to save the battery.
	// Invoking a lengthy asynchronous method within this listener method can be risky, because it is not guaranteed to invoke a
	// callback before the device enters the sleep mode.
	// Similarly, do not perform lengthy operations in this listener method. Any operation must be a quick one.
}
Kevin Raine
I think I've ascertained the cause of my problem ... the audio API's must be called in the context of the UI thread. My application is structured such that the Audio Output API's are called from a thread other than the UI thread (which was created using pthread_create()). I can get around the issue by using SendUserEvent() to send an async event to the OnUserEventReceivedN() method in my main UI thread. If I call "__audioOut.Construct(*this)" from OnUserEventReceivedN(), it returns success. (Ollanketo: Thanks for taking the time to reply to my post)
Kevin Raine
Clarification of my previous comment ... > the audio API's must be called in the context of the UI thread. The audio API's must be called in the context of a Tizen thread (ie not a pthread).