1/*
2 * Copyright © 2000-2006 Ingo Weinhold <ingo_weinhold@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT licensce.
4 */
5#include <algorithm>
6#include <string.h>
7
8#include "AudioReader.h"
9
10using std::swap;
11
12
13AudioReader::AudioReader()
14	: fFormat(),
15	  fOutOffset(0)
16{
17}
18
19
20AudioReader::AudioReader(const media_format& format)
21	: fFormat(format),
22	  fOutOffset(0)
23{
24}
25
26
27AudioReader::~AudioReader()
28{
29}
30
31
32status_t
33AudioReader::InitCheck() const
34{
35	return B_OK;
36}
37
38
39void
40AudioReader::SetFormat(const media_format& format)
41{
42	fFormat = format;
43}
44
45
46const media_format&
47AudioReader::Format() const
48{
49	return fFormat;
50}
51
52
53void
54AudioReader::SetOutOffset(int64 offset)
55{
56	fOutOffset = offset;
57}
58
59
60int64
61AudioReader::OutOffset() const
62{
63	return fOutOffset;
64}
65
66
67int64
68AudioReader::FrameForTime(bigtime_t time) const
69{
70	double frameRate = fFormat.u.raw_audio.frame_rate;
71	return int64(double(time) * frameRate / 1000000.0);
72}
73
74
75bigtime_t
76AudioReader::TimeForFrame(int64 frame) const
77{
78	double frameRate = fFormat.u.raw_audio.frame_rate;
79	return bigtime_t(double(frame) * 1000000.0 / frameRate);
80}
81
82
83//! helper function for ReadSilence()
84template<typename sample_t>
85inline void
86fill_buffer(void* buffer, int32 count, sample_t value)
87{
88	sample_t* buf = (sample_t*)buffer;
89	sample_t* bufferEnd = buf + count;
90	for (; buf < bufferEnd; buf++)
91		*buf = value;
92}
93
94
95/*! Fills the supplied buffer with /frames/ frames of silence and returns a
96	pointer to the frames after the filled range.
97	/frames/ must be >= 0.*/
98void*
99AudioReader::ReadSilence(void* buffer, int64 frames) const
100{
101	void* bufferEnd = SkipFrames(buffer, frames);
102	int32 sampleCount = frames * fFormat.u.raw_audio.channel_count;
103	switch (fFormat.u.raw_audio.format) {
104		case media_raw_audio_format::B_AUDIO_FLOAT:
105			fill_buffer(buffer, sampleCount, (float)0);
106			break;
107		case media_raw_audio_format::B_AUDIO_INT:
108			fill_buffer(buffer, sampleCount, (int)0);
109			break;
110		case media_raw_audio_format::B_AUDIO_SHORT:
111			fill_buffer(buffer, sampleCount, (short)0);
112			break;
113		case media_raw_audio_format::B_AUDIO_UCHAR:
114			fill_buffer(buffer, sampleCount, (uchar)128);
115			break;
116		case media_raw_audio_format::B_AUDIO_CHAR:
117			fill_buffer(buffer, sampleCount, (uchar)0);
118			break;
119		default:
120			memset(buffer, 0, (char*)bufferEnd - (char*)buffer);
121			break;
122 	}
123	return bufferEnd;
124}
125
126
127//! Returns a buffer pointer offset by /frames/ frames.
128void*
129AudioReader::SkipFrames(void* buffer, int64 frames) const
130{
131	int32 sampleSize = fFormat.u.raw_audio.format
132		& media_raw_audio_format::B_AUDIO_SIZE_MASK;
133	int32 frameSize = sampleSize * fFormat.u.raw_audio.channel_count;
134	return (char*)buffer + frames * frameSize;
135}
136
137
138void
139AudioReader::ReverseFrames(void* buffer, int64 frames) const
140{
141	int32 sampleSize = fFormat.u.raw_audio.format
142		& media_raw_audio_format::B_AUDIO_SIZE_MASK;
143	int32 frameSize = sampleSize * fFormat.u.raw_audio.channel_count;
144	char* front = (char*)buffer;
145	char* back = (char*)buffer + (frames - 1) * frameSize;
146	while (front < back) {
147		for (int32 i = 0; i < frameSize; i++)
148			swap(front[i], back[i]);
149		front += frameSize;
150		back -= frameSize;
151	}
152}
153
154