forked from nu774/qaac
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrawsource.cpp
More file actions
71 lines (66 loc) · 2.61 KB
/
rawsource.cpp
File metadata and controls
71 lines (66 loc) · 2.61 KB
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
#include "rawsource.h"
#include "win32util.h"
#include "cautil.h"
RawSource::RawSource(const std::shared_ptr<FILE> &fp,
const AudioStreamBasicDescription &asbd)
: m_position(0), m_fp(fp), m_asbd(asbd)
{
if (isSeekable())
m_length = _filelengthi64(fileno(m_fp.get())) / asbd.mBytesPerFrame;
else
m_length = ~0ULL;
bool isfloat = asbd.mFormatFlags & kAudioFormatFlagIsFloat;
m_oasbd = cautil::buildASBDForPCM2(asbd.mSampleRate,
asbd.mChannelsPerFrame,
asbd.mBitsPerChannel,
isfloat ? asbd.mBitsPerChannel : 32,
isfloat ? kAudioFormatFlagIsFloat
: kAudioFormatFlagIsSignedInteger);
}
size_t RawSource::readSamples(void *buffer, size_t nsamples)
{
ssize_t nbytes = nsamples * m_asbd.mBytesPerFrame;
if (m_buffer.size() < nbytes)
m_buffer.resize(nbytes);
nbytes = util::nread(fileno(m_fp.get()), &m_buffer[0], nbytes);
nsamples = nbytes > 0 ? nbytes / m_asbd.mBytesPerFrame : 0;
if (nsamples) {
size_t size = nsamples * m_asbd.mBytesPerFrame;
/* bswap */
if (m_asbd.mFormatFlags & kAudioFormatFlagIsBigEndian)
util::bswapbuffer(&m_buffer[0], size,
(m_asbd.mBitsPerChannel + 7) & ~7);
util::unpack(&m_buffer[0], buffer, &size,
m_asbd.mBytesPerFrame / m_asbd.mChannelsPerFrame,
m_oasbd.mBytesPerFrame / m_oasbd.mChannelsPerFrame);
/* convert to signed */
if (!(m_asbd.mFormatFlags & kAudioFormatFlagIsFloat) &&
!(m_asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger))
{
util::convert_sign(static_cast<uint32_t *>(buffer),
nsamples * m_asbd.mChannelsPerFrame);
}
}
m_position += nsamples;
return nsamples;
}
void RawSource::seekTo(int64_t count)
{
int fd = fileno(m_fp.get());
if (isSeekable()) {
CHECKCRT(_lseeki64(fd, count*m_asbd.mBytesPerFrame, SEEK_SET) < 0);
m_position = count;
} else if (m_position > count) {
throw std::runtime_error("Cannot seek back the input");
} else {
int64_t bytes = (count - m_position) * m_asbd.mBytesPerFrame;
int64_t nread = 0;
char buf[0x1000];
while (nread < bytes) {
int n = util::nread(fd, buf, std::min(bytes - nread, 0x1000LL));
if (n <= 0) break;
nread += n;
}
m_position += nread / m_asbd.mBytesPerFrame;
}
}