forked from ZLMediaKit/ZLMediaKit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAudioSRC.cpp
136 lines (116 loc) · 4.05 KB
/
AudioSRC.cpp
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include "Util/logger.h"
#include "AudioSRC.h"
#include "SDLAudioDevice.h"
using namespace std;
using namespace toolkit;
AudioSRC::AudioSRC(AudioSRCDelegate *del) {
_delegate = del;
}
AudioSRC::~AudioSRC() {}
void AudioSRC::setOutputAudioConfig(const SDL_AudioSpec &cfg) {
int freq = _delegate->getPCMSampleRate();
int format = _delegate->getPCMFormat();
int channels = _delegate->getPCMChannel();
if (-1 == SDL_BuildAudioCVT(&_audio_cvt, format, channels, freq, cfg.format, cfg.channels, cfg.freq)) {
throw std::runtime_error("the format conversion is not supported");
}
InfoL << "audio cvt origin format, freq:" << freq << ", format:" << hex << format << dec << ", channels:" << channels;
InfoL << "audio cvt info, "
<< "needed:" << (int)_audio_cvt.needed
<< ", src_format:" << hex << (SDL_AudioFormat)_audio_cvt.src_format
<< ", dst_format:" << (SDL_AudioFormat)_audio_cvt.dst_format << dec
<< ", rate_incr:" << (double)_audio_cvt.rate_incr
<< ", len_mult:" << (int)_audio_cvt.len_mult
<< ", len_ratio:" << (double)_audio_cvt.len_ratio;
}
void AudioSRC::setEnableMix(bool flag) {
_enabled = flag;
}
int AudioSRC::getPCMData(char *buf, int size) {
if (!_enabled) {
return 0;
}
if (!_audio_cvt.needed) {
//获取原始数据,不需要频率转换
return _delegate->getPCMData(buf, size);
}
//对应的未转换前pcm的长度
auto original_size = (int) (size / _audio_cvt.len_ratio);
if (original_size % 4 != 0) {
//必须为4byte的整数(双通道16bit一个采样就4个字节)
original_size = 4 * (original_size / 4) + 4;
}
//需要准备这么长的buf用于重采样
if ((int) (original_size * _audio_cvt.len_mult) != _buf_size) {
_buf_size = original_size * _audio_cvt.len_mult;
_buf.reset(new char[_buf_size], [](char *ptr) {
delete[] ptr;
});
InfoL << "origin pcm buffer size is:" << original_size << ", target pcm buffer size is:" << size;
}
auto origin_size = _delegate->getPCMData(_buf.get(), original_size );
if (!origin_size) {
//获取数据失败
TraceL << "get empty pcm data";
return 0;
}
_audio_cvt.buf = (Uint8 *) _buf.get();
_audio_cvt.len = origin_size;
if (0 != SDL_ConvertAudio(&_audio_cvt)) {
WarnL << "SDL_ConvertAudio failed!";
_audio_cvt.len_cvt = 0;
}
if (_audio_cvt.len_cvt) {
_target_buf.append(_buf.get(), _audio_cvt.len_cvt);
}
if (_target_buf.size() < (size_t)size) {
return 0;
}
memcpy(buf, _target_buf.data(), size);
_target_buf.erase(0, size);
return size;
}
////////////////////////////////////////////////////////////////////////
AudioPlayer::AudioPlayer() : AudioSRC(this) {
_device = SDLAudioDevice::Instance().shared_from_this();
}
AudioPlayer::~AudioPlayer() {
_device->delChannel(this);
}
void AudioPlayer::setup(int sample_rate, int channel, SDL_AudioFormat format) {
_sample_rate = sample_rate;
_channel = channel;
_format = format;
_device->addChannel(this);
}
SDL_AudioFormat AudioPlayer::getPCMFormat() {
return _format;
}
int AudioPlayer::getPCMSampleRate() {
return _sample_rate;
}
int AudioPlayer::getPCMChannel() {
return _channel;
}
int AudioPlayer::getPCMData(char *buf, int size) {
lock_guard<mutex> lck(_mtx);
if (_buffer.size() < (size_t)size) {
return 0;
}
memcpy(buf, _buffer.data(), size);
_buffer.erase(0, size);
return size;
}
void AudioPlayer::playPCM(const char *data, size_t size) {
lock_guard<mutex> lck(_mtx);
_buffer.append(data, size);
}