소리 재생 API¶
확장자가 .wav인 WAVE 포맷의 음악 파일을 재생합니다. 두가지 방식을 지원합니다.
-
playSound함수는 소리 재생이 시작되면 마칠 때까지 재생이 되며 도중에 중단할 수 없습니다. -
SoundPlayer객체를 사용하여 MediaObserver로 유도된 사용자 정의 이벤트 콜백 클래스를 이용합니다.
헤더 파일¶
OasisMedia.h
함수¶
int32_t
playSound
(
const char *
file_path
,
const char *
snd_path
)
OasisMedia.h
WAVE 파일을 재생합니다. 바로 리턴됩니다. 연속하여 호출할 경우, 소리는 믹스되어 재생됩니다.
매개변수
file_path
WAVE 파일 경로입니다.
snd_path
createAudioDevice 호출로 생성된 오디오 장치 경로입니다.
리턴값
- 0: 성공
- -1: 실패
SoundPlayerRef
createSoundPlayer
(
const char *
file_path
,
key_value_map_t &
parameters
)
OasisMedia.h
SoundPlayer 객체를 생성합니다.
매개변수
file_path
WAVE 파일 경로입니다.
parameters
SoundPlayer 객체 생성에 필요한 key-value map 입니다.
리턴값
성공하면 SoundPlayer 객체를 리턴합니다. 실패하면 nullptr을 리턴합니다.
SoundPlayer 객체 생성에 필요한 key-value map은 아래와 같습니다.
키
기본값
필수
설명
snd-path
○
createAudioDevice 호출로 생성된 오디오 장치 경로입니다.
int32_t
setSoundPlayerObserver
(
const SoundPlayerRef &
sound_player
,
const std::shared_ptr<MediaObserver> &
observer
,
void *
user_data
)
OasisMedia.h
MediaObserver를 설정합니다.
매개변수
sound_player
SoundPlayer 객체입니다.
observer
MediaObserver에서 유도된 사용자 정의 observer 객체입니다.
user_data
MediaObserver의 콜백 함수의 매개변수로 사용될 사용자 정의 데이터입니다.
리턴값
- 0: 성공
- -1: 실패
int32_t
destroySoundPlayer
(
const SoundPlayerRef &
sound_player
)
OasisMedia.h
SoundPlayer 객체를 해제합니다.
매개변수
sound_player
SoundPlayer 객체입니다.
리턴값
- 0: 성공
- -1: 실패
int32_t
startSoundPlayer
(
const SoundPlayerRef &
sound_player
)
OasisMedia.h
소리 재생을 시작합니다.
매개변수
sound_player
SoundPlayer 객체입니다.
리턴값
- 0: 성공
- -1: 실패
int32_t
stopSoundPlayer
(
const SoundPlayerRef &
sound_player
)
OasisMedia.h
소리 재생을 중지합니다.
매개변수
sound_player
SoundPlayer 객체입니다.
리턴값
- 0: 성공
- -1: 실패
bool
isSoundPlaying
(
const SoundPlayerRef &
sound_player
)
OasisMedia.h
재생 중인지 상태를 확인합니다.
매개변수
sound_player
SoundPlayer 객체입니다.
리턴값
- true: 재생중입니다.
- false: 재생하고 있지 않습니다.
예제¶
아래는 WAV 파일을 재생하는 예제입니다.
MediaObserver로 부터 유도된 사용자 정의 Observer 클래스를 정의합니다.
class SoundPlayingObserver : public oasis::MediaObserver
{
public:
SoundPlayingObserver();
virtual ~SoundPlayingObserver();
public:
virtual void onStarted(void* user_data, const char* file_path);
virtual void onStopped(void* user_data, media_report_reason_t reason, void* details);
virtual void onError(void* user_data, media_report_reason_t reason, void* details);
virtual void onInfo(void* user_data, MediaInfo* info);
};
SoundPlayingObserver::SoundPlayingObserver()
{
}
SoundPlayingObserver::~SoundPlayingObserver()
{
}
void SoundPlayingObserver::onStarted(void* user_data, const char* file_path)
{
fprintf(stdout, "Playing started, file path \"%s\"\n", file_path);
}
void SoundPlayingObserver::onStopped(void* user_data, media_report_reason_t reason, void* details)
{
fprintf(stdout, "Playing stopped, reason: %d\n", reason);
got_interrupt = true;
}
void SoundPlayingObserver::onError(void* user_data, media_report_reason_t reason, void* details)
{
got_interrupt = true;
}
void SoundPlayingObserver::onInfo(void* user_data, MediaInfo* info)
{
int h, m, s, u;
parseUsec(info->durationUs, h, m, s, u);
int ch, cm, cs, cu;
parseUsec(info->currentTimestampUs, ch, cm, cs, cu);
fprintf(stdout, "Playing duration %02d:%02d:%02d.%06d, current %02d:%02d:%02d.%06d \r", h, m, s, u, ch, cm, cs, cu);
fflush(stdout);
}
Oasis를 초기화합니다.
oasis::key_value_map_t parameters;
parameters["offs-disable"] = "1";
if(oasis::initialize(parameters) < 0) {
DLOG(DLOG_ERROR, "Oasis init failed\n");
return -1;
}
오디오 장치를 초기화 합니다.
#if 0
#define SND_PATH "default"
#else
#define SND_PATH "hw:0,0"
#endif
parameters["types"]="source,sink";
parameters["path"]=SND_PATH;
parameters["always-on"]="1";
parameters["channels"]="2";
parameters["aec-disabled"]="1";
parameters["snd-input-channels"]="2";
parameters["snd-input-sample-size"]="16";
parameters["snd-input-sampling-duration-msec"]="40";
parameters["snd-input-sampling-rate"]="48000";
createAudioDevice(parameters);
플레이어 객체를 생성하고 재생을 시작합니다.
SoundPlayerRef player = nullptr;
std::shared_ptr<SoundPlayingObserver> observer = std::make_shared<SoundPlayingObserver>();
parameters.clear();
parameters["snd-path"] = SND_PATH;
player = createSoundPlayer(argv[1], parameters);
ASSERT(player);
if(player != nullptr) {
//set observer.
setSoundPlayerObserver(player, observer, nullptr);
if(startSoundPlayer(player) == 0) {
} else {
fprintf(stdout, "playing \"%s\" start failed.\n", argv[1]);
}
} else {
fprintf(stdout, "playing \"%s\" creation failed.\n", argv[1]);
}
재생을 마치면 종료합니다.
do {
usleep(100000);
} while(got_interrupt == false);
if(player) {
destroySoundPlayer(player);
}
oasis::finalize();
아래는 전체 코드입니다.
#include "OasisAPI.h"
#include "OasisLog.h"
#include "OasisUtil.h"
#include "OasisMedia.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <thread>
#include <mutex>
#include <memory>
#include <condition_variable>
#undef DLOG_TAG
#define DLOG_TAG "Sound"
#define OFFS_QUEUE_SIZE_KBYTES (40*1024)
#define OFFS_CACHE_SIZE_KBYTES (1024)
#define OFFS_WRITE_ALIGNMENT_BYTES 8192
#define MEDIA_CACHE_SIZE_KBYTES (40*1024)
using namespace oasis;
bool got_interrupt = false;
#include <signal.h>
class SoundPlayingObserver : public oasis::MediaObserver
{
public:
SoundPlayingObserver();
virtual ~SoundPlayingObserver();
public:
virtual void onStarted(void* user_data, const char* file_path);
virtual void onStopped(void* user_data, media_report_reason_t reason, void* details);
virtual void onError(void* user_data, media_report_reason_t reason, void* details);
virtual void onInfo(void* user_data, MediaInfo* info);
};
SoundPlayingObserver::SoundPlayingObserver()
{
}
SoundPlayingObserver::~SoundPlayingObserver()
{
}
void SoundPlayingObserver::onStarted(void* user_data, const char* file_path)
{
fprintf(stdout, "Playing started, file path \"%s\"\n", file_path);
}
void SoundPlayingObserver::onStopped(void* user_data, media_report_reason_t reason, void* details)
{
fprintf(stdout, "Playing stopped, reason: %d\n", reason);
got_interrupt = true;
}
void SoundPlayingObserver::onError(void* user_data, media_report_reason_t reason, void* details)
{
fprintf(stdout, "Playing Error, reason: %d\n", reason);
got_interrupt = true;
}
void SoundPlayingObserver::onInfo(void* user_data, MediaInfo* info)
{
int h, m, s, u;
parseUsec(info->durationUs, h, m, s, u);
int ch, cm, cs, cu;
parseUsec(info->currentTimestampUs, ch, cm, cs, cu);
fprintf(stdout, "Playing duration %02d:%02d:%02d.%06d, current %02d:%02d:%02d.%06d \r", h, m, s, u, ch, cm, cs, cu);
fflush(stdout);
}
void cancel_handler(int sig)
{
got_interrupt = true;
}
int main(int argc, char *argv[])
{
int32_t err;
signal(SIGINT, cancel_handler);
oasis::key_value_map_t parameters;
if(argc < 2) {
fprintf(stdout, "USAGE: %s <wave file path>\n", argv[0]);
return -1;
}
if(access(argv[1], F_OK)) {
fprintf(stderr, "file not found: %s\n", argv[1]);
return -1;
}
parameters["offs-disable"] = "1";
if(oasis::initialize(parameters) < 0) {
DLOG(DLOG_ERROR, "Oasis init failed\n");
return -1;
}
#if 0
#define SND_PATH "default"
#else
#define SND_PATH "hw:0,0"
#endif
parameters["types"]="source,sink";
parameters["path"]=SND_PATH;
parameters["always-on"]="1";
parameters["channels"]="2";
parameters["aec-disabled"]="1";
parameters["snd-input-channels"]="2";
parameters["snd-input-sample-size"]="16";
parameters["snd-input-sampling-duration-msec"]="40";
parameters["snd-input-sampling-rate"]="48000";
//parameters["snd-input-sampling-rate"]="22050";
createAudioDevice(parameters);
SoundPlayerRef player = nullptr;
std::shared_ptr<SoundPlayingObserver> observer = std::make_shared<SoundPlayingObserver>();
parameters.clear();
parameters["snd-path"] = SND_PATH;
player = createSoundPlayer(argv[1], parameters);
ASSERT(player);
if(player != nullptr) {
//set observer.
setSoundPlayerObserver(player, observer, nullptr);
if(startSoundPlayer(player) == 0) {
} else {
fprintf(stdout, "playing \"%s\" start failed.\n", argv[1]);
}
} else {
fprintf(stdout, "playing \"%s\" creation failed.\n", argv[1]);
}
fprintf(stdout, "Enter Ctrl+C to exit...\n");
do {
usleep(100000);
} while(got_interrupt == false);
if(player) {
destroySoundPlayer(player);
}
oasis::finalize();
return 0;
}