Coding & Programming/C, C++, SFML

[C/C++, SFML] 7. 오디오(음악, 효과음) 파일 읽고 재생하기(SoundBuffer, Sound)

mainCodes 2021. 3. 30. 09:32

안녕하세요 JollyTree입니다 (•̀ᴗ•́)و

 

오디오 파일은 sf::SoundBuffer 클래스를 통해 메모리로 읽을 수 있습니다. 전반적인 절차는 폰트를 읽고 화면에
Text를 출력하는 것과 유사합니다.

 

폰트의 경우 sf::Font 클래스의 loadFromFile() 메소드를 이용하여 읽고 sf::Text 클래스를 이용하여 색, 위치, 크기 등을 지정했듯이 오디오 파일의 경우도 sf::SoundBuffer 클래스를 이용하여 오디오 파일을 읽고 sf::Sound 클래스를 이용하여 피치 설정, 플레이 등을 수행합니다. 오디오 데이터를 파일 뿐만 아니라 스트림 또는 메모리로부터도 읽을 수 있습니다.

 

SFML이 지원하는 오디오 파일 포멧은 WAV, OGG, FLAC이며 MP3는 라이센스 이슈로 현재 지원하지 않고 있습니다.

오디오 파일을 읽고 플레이 하는 기본 과정은 다음과 같습니다.

 


sf::SoundBuffer buffer;

buff.loadFromFile("images\\start.wav");

sf::Sound sound(buffer)

sound.play();   //오디오 재생

sound.setPlayingOffset(sf:seconds(2.f)); //2초부터 재생

sound.pause(); //재생 일시 멈춤

sound.play();   //플레이

sound.stop();   //재생 정지

이 외에도 Sound 클래스는 피치, 볼륨, 반복재생 등을 할 수 있는 setPitch(), setVolume(), setLoop() 등의 메소드를 지원합니다. 자세한 사항은 SFML(www.sfml-dev.org/) Sound 클래스에 대한 문서 파일을 읽어 보는 것을 추천합니다.

 

예제는 play_sound_detail() 함수를 통해 오디오 파일을 플레이하고 플레이하는 동안 상세한 정보(총 재생시간, 채널, 플레이 오프셋 정보 등)를 출력함으로써 오디오 플레이 전반에 대해 설명합니다. 오디오 파일은 일정 시간(초) 간격으로 플레이되며 main()함수내의 SoundBuffer buffer, Sound sound는 오디오 파일을 먼저 읽고 알맞은 시기에 .play() 메소드를 이용하여 오디오를 출력하는 것을 보여줍니다.

 

타이머 예제는 "[C/C++, SFML] 4. 타이머(Timer) 구현하기"를 기반으로 합니다. 예제는 오디오 출력을 위해 "Audio.hpp" 헤더 파일이 추가되었습니다.

 

SFML SoundBuffer, Sound 예제 소스코드(Example):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
 
using namespace std;
using namespace sf;
 
void play_sound_detail(const std::string& filename)
{
    SoundBuffer buffer;
    //오디오 파일 읽기
    if (!buffer.loadFromFile(filename))
    {
        cout << "loadFromFile 에러" << endl;
        return;
    }
 
    //오디오 정보 출력
    cout << filename << "을 재생 중:" << endl;
    cout << " " << buffer.getDuration().asSeconds() << " 초" << endl;
    cout << " " << buffer.getSampleRate() << " samples / 초" << endl;
    cout << " " << buffer.getChannelCount() << " 채널" << endl;
 
    //오디오 재생
    Sound sound(buffer);
    sound.play();
 
    //소리가 재생되는 동안 루프
    while (sound.getStatus() == Sound::Playing)
    {
        sleep(sf::milliseconds(100));
 
        //재생 위치
        cout << "\r재생 중... " << sound.getPlayingOffset().asSeconds() << " 초        ";
        cout << flush;
    }
    cout << endl << endl;
}
 
int main()
{
    Clock clock; //경과 시간을 측정할 수있는 Clock객체 선언
    float interval = 0;
 
    SoundBuffer buffer;
    //오디오 파일 읽기
    if (!buffer.loadFromFile("resources/concentration.wav"))
    {
        cout << "loadFromFile 에러" << endl;
        return -1;
    }
    Sound sound(buffer);
 
    cout << "프로그램이 시작되었습니다." << endl;
 
    //화면 크기, 캡션 이름 설정
    RenderWindow app(VideoMode(504504), "https://maincodes.tistory.com/");
    app.setFramerateLimit(60);  //프레임 비율 설정
 
    //SFML 메인 루프 - 윈도우가 닫힐때 까지 반복
    while (app.isOpen())
    {
        float time = clock.getElapsedTime().asSeconds();
        clock.restart();
 
        interval += time;
 
        Event event;
 
        //이벤트 처리
        while (app.pollEvent(event))
        {
            //프로그램 종료 이벤트 처리
            if (event.type == Event::EventType::Closed)
            {
                app.close();
                cout << "프로그램이 종료되었습니다." << endl;
            }
        }
        if (((int)interval % 5== 0)
        {
            cout << "inteval = " << interval << endl;
            play_sound_detail("resources/Lightning.wav");
 
            //sound 플레이
            cout << "resources/concentration.wav 재생 " << endl;
            sound.play();
        }
 
        //배경화면을 흰색으로 clear
        app.clear(Color::White);
 
 
        //프레임을 스크린에 출력
        app.display();
    }
 
    return 0;
}
cs

 

실행결과(Output):

 

이상 JollyTree였습니다 (•̀ᴗ•́)و