* The AudioProducer now correctly handles late producer notices by ignoring

extra notices for buffers already scheduled.
* Also, the AudioSupplier/AudioReader classes now know their initial latency,
  and the AudioProducer is now using that one to advertize its own initial
  latency - this fixes late buffers on start, causing the latency to grow
  too large.
* Cleanup here and there.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36199 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-04-12 20:36:19 +00:00
parent 02af02f93a
commit 8dd3060da4
19 changed files with 370 additions and 243 deletions
@@ -77,6 +77,13 @@ AudioAdapter::~AudioAdapter()
}
bigtime_t
AudioAdapter::InitialLatency() const
{
return fSource->InitialLatency();
}
status_t
AudioAdapter::Read(void* buffer, int64 pos, int64 frames)
{
@@ -1,7 +1,10 @@
/*
* Copyright © 2000-2006 Ingo Weinhold <[email protected]>
* Copyright 2000-2006 Ingo Weinhold <[email protected]>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#ifndef AUDIO_ADAPTER_H
#define AUDIO_ADAPTER_H
/*! This AudioReader slaves an AudioConverter and an AudioResampler
to convert the source data to a given format.
@@ -10,21 +13,22 @@
If input and output format are the same, the overhead is quit small.
*/
#ifndef AUDIO_ADAPTER_H
#define AUDIO_ADAPTER_H
#include "AudioReader.h"
class AudioChannelConverter;
class AudioFormatConverter;
class AudioResampler;
class AudioAdapter : public AudioReader {
public:
AudioAdapter(AudioReader* source,
const media_format& format);
virtual ~AudioAdapter();
virtual bigtime_t InitialLatency() const;
virtual status_t Read(void* buffer, int64 pos, int64 frames);
virtual status_t InitCheck() const;
@@ -1,7 +1,9 @@
/*
* Copyright © 2008 Stephan Aßmus <[email protected]>
* Copyright 2008 Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#include "AudioChannelConverter.h"
#include <new>
@@ -10,29 +12,15 @@
using std::nothrow;
//#define TRACE_AUDIO_CONVERTER
#ifdef TRACE_AUDIO_CONVERTER
# define TRACE(x...) printf(x)
# define TRACE(x...) printf(x)
#else
# define TRACE(x...)
# define TRACE(x...)
#endif
AudioChannelConverter::AudioChannelConverter(AudioReader* source,
const media_format& format)
: AudioReader(format),
fSource(source)
{
// TODO: check the format and make sure everything matches
// except for channel count
}
AudioChannelConverter::~AudioChannelConverter()
{
}
template<typename Type, typename BigType>
static void
convert(Type* inBuffer, Type* outBuffer, int32 inChannels, int32 outChannels,
@@ -79,6 +67,31 @@ convert(Type* inBuffer, Type* outBuffer, int32 inChannels, int32 outChannels,
}
// #pragma mark -
AudioChannelConverter::AudioChannelConverter(AudioReader* source,
const media_format& format)
: AudioReader(format),
fSource(source)
{
// TODO: check the format and make sure everything matches
// except for channel count
}
AudioChannelConverter::~AudioChannelConverter()
{
}
bigtime_t
AudioChannelConverter::InitialLatency() const
{
fSource->InitialLatency();
}
status_t
AudioChannelConverter::Read(void* outBuffer, int64 pos, int64 frames)
{
@@ -1,24 +1,27 @@
/*
* Copyright © 2008 Stephan Aßmus <[email protected]>
* Copyright 2008 Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#ifndef AUDIO_CHANNEL_CONVERTER_H
#define AUDIO_CHANNEL_CONVERTER_H
/*! This AudioReader just converts the source channel count
into another one, e.g. 1 -> 2. Frame rate and sample format
remain unchanged.
*/
#ifndef AUDIO_CHANNEL_CONVERTER_H
#define AUDIO_CHANNEL_CONVERTER_H
#include "AudioReader.h"
class AudioChannelConverter : public AudioReader {
public:
AudioChannelConverter(AudioReader* source,
const media_format& format);
virtual ~AudioChannelConverter();
virtual bigtime_t InitialLatency() const;
virtual status_t Read(void* buffer, int64 pos, int64 frames);
virtual status_t InitCheck() const;
@@ -1,9 +1,10 @@
/*
* Copyright © 2000-2006 Ingo Weinhold <[email protected]>
* Copyright © 2008 Stephan Aßmus <[email protected]>
* Copyright 2000-2006 Ingo Weinhold <[email protected]>
* Copyright 2008 Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#include "AudioFormatConverter.h"
#include <ByteOrder.h>
@@ -12,44 +13,12 @@
//#define TRACE_AUDIO_CONVERTER
#ifdef TRACE_AUDIO_CONVERTER
# define TRACE(x...) printf(x)
# define TRACE(x...) printf(x)
#else
# define TRACE(x...)
# define TRACE(x...)
#endif
AudioFormatConverter::AudioFormatConverter(AudioReader* source, uint32 format,
uint32 byte_order)
: AudioReader(),
fSource(NULL)
{
uint32 hostByteOrder
= (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
if (source && source->Format().type == B_MEDIA_RAW_AUDIO
&& source->Format().u.raw_audio.byte_order == hostByteOrder) {
fFormat = source->Format();
fFormat.u.raw_audio.format = format;
fFormat.u.raw_audio.byte_order = byte_order;
int32 inSampleSize = source->Format().u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK;
int32 outSampleSize = fFormat.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK;
if (inSampleSize != outSampleSize) {
fFormat.u.raw_audio.buffer_size
= source->Format().u.raw_audio.buffer_size * outSampleSize
/ inSampleSize;
}
} else
source = NULL;
fSource = source;
}
AudioFormatConverter::~AudioFormatConverter()
{
}
struct ReadFloat {
inline int operator()(const void* buffer) const {
// 0 == mid, -1.0 == bottom, 1.0 == top
@@ -150,8 +119,7 @@ convert(const ReadT& read, const WriteT& write,
}
static
void
static void
swap_sample_byte_order(void* buffer, uint32 format, size_t length)
{
type_code type = B_ANY_TYPE;
@@ -175,6 +143,48 @@ swap_sample_byte_order(void* buffer, uint32 format, size_t length)
}
// #pragma mark -
AudioFormatConverter::AudioFormatConverter(AudioReader* source, uint32 format,
uint32 byte_order)
:
AudioReader(),
fSource(NULL)
{
uint32 hostByteOrder
= (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
if (source && source->Format().type == B_MEDIA_RAW_AUDIO
&& source->Format().u.raw_audio.byte_order == hostByteOrder) {
fFormat = source->Format();
fFormat.u.raw_audio.format = format;
fFormat.u.raw_audio.byte_order = byte_order;
int32 inSampleSize = source->Format().u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK;
int32 outSampleSize = fFormat.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK;
if (inSampleSize != outSampleSize) {
fFormat.u.raw_audio.buffer_size
= source->Format().u.raw_audio.buffer_size * outSampleSize
/ inSampleSize;
}
} else
source = NULL;
fSource = source;
}
AudioFormatConverter::~AudioFormatConverter()
{
}
bigtime_t
AudioFormatConverter::InitialLatency() const
{
fSource->InitialLatency();
}
status_t
AudioFormatConverter::Read(void* buffer, int64 pos, int64 frames)
{
@@ -1,25 +1,28 @@
/*
* Copyright © 2000-2006 Ingo Weinhold <[email protected]>
* Copyright © 2008 Stephan Aßmus <[email protected]>
* Copyright 2000-2006 Ingo Weinhold <[email protected]>
* Copyright 2008 Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#ifndef AUDIO_FORMAT_CONVERTER_H
#define AUDIO_FORMAT_CONVERTER_H
/*! This AudioReader just converts the source sample format (and byte order)
into another one, e.g. LE short -> BE float. Frame rate and channel
count remain unchanged.
*/
#ifndef AUDIO_FORMAT_CONVERTER_H
#define AUDIO_FORMAT_CONVERTER_H
#include "AudioReader.h"
class AudioFormatConverter : public AudioReader {
public:
AudioFormatConverter(AudioReader* source,
uint32 format, uint32 byte_order);
virtual ~AudioFormatConverter();
virtual bigtime_t InitialLatency() const;
virtual status_t Read(void* buffer, int64 pos, int64 frames);
virtual status_t InitCheck() const;
@@ -37,13 +37,13 @@
// debugging
//#define TRACE_AUDIO_PRODUCER
#ifdef TRACE_AUDIO_PRODUCER
# define TRACE(x...) printf(x)
# define TRACE_BUFFER(x...)
# define ERROR(x...) fprintf(stderr, x)
# define TRACE(x...) printf(x)
# define TRACE_BUFFER(x...)
# define ERROR(x...) fprintf(stderr, x)
#else
# define TRACE(x...)
# define TRACE_BUFFER(x...)
# define ERROR(x...) fprintf(stderr, x)
# define TRACE(x...)
# define TRACE_BUFFER(x...)
# define ERROR(x...) fprintf(stderr, x)
#endif
@@ -85,24 +85,63 @@ init_media_file(media_format format, BMediaTrack** _track)
#endif // DEBUG_TO_FILE
static bigtime_t
estimate_internal_latency(const media_format& format)
{
bigtime_t startTime = system_time();
// calculate the number of samples per buffer
int32 sampleSize = format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK;
int32 sampleCount = format.u.raw_audio.buffer_size / sampleSize;
// alloc float buffers of this size
const int bufferCount = 10; // number of input buffers
float* buffers[bufferCount + 1];
for (int32 i = 0; i < bufferCount + 1; i++)
buffers[i] = new float[sampleCount];
float* outBuffer = buffers[bufferCount];
// fill all buffers save the last one with arbitrary data and merge them
// into the last one
for (int32 i = 0; i < bufferCount; i++) {
for (int32 k = 0; k < sampleCount; k++) {
buffers[i][k] = ((float)i * (float)k)
/ float(bufferCount * sampleCount);
}
}
for (int32 k = 0; k < sampleCount; k++) {
outBuffer[k] = 0;
for (int32 i = 0; i < bufferCount; i++)
outBuffer[k] += buffers[i][k];
outBuffer[k] /= bufferCount;
}
// cleanup
for (int32 i = 0; i < bufferCount + 1; i++)
delete[] buffers[i];
return system_time() - startTime;
}
// #pragma mark -
// constructor
AudioProducer::AudioProducer(const char* name, AudioSupplier* supplier,
bool lowLatency)
: BMediaNode(name),
BBufferProducer(B_MEDIA_RAW_AUDIO),
BMediaEventLooper(),
:
BMediaNode(name),
BBufferProducer(B_MEDIA_RAW_AUDIO),
BMediaEventLooper(),
fBufferGroup(NULL),
fLatency(0),
fInternalLatency(0),
fLowLatency(lowLatency),
fOutputEnabled(true),
fFramesSent(0),
fStartTime(0),
fSupplier(supplier),
fBufferGroup(NULL),
fLatency(0),
fInternalLatency(0),
fLastLateNotice(0),
fNextScheduledBuffer(0),
fLowLatency(lowLatency),
fOutputEnabled(true),
fFramesSent(0),
fStartTime(0),
fSupplier(supplier),
fPeakListener(NULL)
fPeakListener(NULL)
{
TRACE("%p->AudioProducer::AudioProducer(%s, %p, %d)\n", this, name,
supplier, lowLatency);
@@ -135,9 +174,11 @@ AudioProducer::AudioProducer(const char* name, AudioSupplier* supplier,
// we're not connected yet
fOutput.destination = media_destination::null;
fOutput.format = fPreferredFormat;
// init the audio supplier
if (fSupplier) {
if (fSupplier != NULL) {
fSupplier->SetAudioProducer(this);
SetInitialLatency(fSupplier->InitialLatency());
}
}
@@ -359,41 +400,6 @@ AudioProducer::PrepareToConnect(const media_source& what,
}
static bigtime_t
estimate_internal_latency(const media_format& format)
{
bigtime_t startTime = system_time();
// calculate the number of samples per buffer
int32 sampleSize = format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK;
int32 sampleCount = format.u.raw_audio.buffer_size / sampleSize;
// alloc float buffers of this size
const int bufferCount = 10; // number of input buffers
float* buffers[bufferCount + 1];
for (int32 i = 0; i < bufferCount + 1; i++)
buffers[i] = new float[sampleCount];
float* outBuffer = buffers[bufferCount];
// fill all buffers save the last one with arbitrary data and merge them
// into the last one
for (int32 i = 0; i < bufferCount; i++) {
for (int32 k = 0; k < sampleCount; k++) {
buffers[i][k] = ((float)i * (float)k)
/ float(bufferCount * sampleCount);
}
}
for (int32 k = 0; k < sampleCount; k++) {
outBuffer[k] = 0;
for (int32 i = 0; i < bufferCount; i++)
outBuffer[k] += buffers[i][k];
outBuffer[k] /= bufferCount;
}
// cleanup
for (int32 i = 0; i < bufferCount + 1; i++)
delete[] buffers[i];
return system_time() - startTime;
}
void
AudioProducer::Connect(status_t error, const media_source& source,
const media_destination& destination, const media_format& format,
@@ -490,6 +496,13 @@ AudioProducer::LateNoticeReceived(const media_source& what, bigtime_t howMuch,
// If we're late, we need to catch up. Respond in a manner appropriate
// to our current run mode.
if (what == fOutput.source) {
// Ignore the notices for buffers we already send out (or scheduled
// their event) before we processed the last notice
if (fLastLateNotice > performanceTime)
return;
fLastLateNotice = fNextScheduledBuffer;
if (RunMode() == B_RECORDING) {
// ...
} else if (RunMode() == B_INCREASE_LATENCY) {
@@ -595,9 +608,10 @@ AudioProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
TRACE("AudioProducer::HandleEvent(B_START)\n");
if (RunState() != B_STARTED) {
fFramesSent = 0;
fStartTime = event->event_time;
fStartTime = event->event_time + fSupplier->InitialLatency();
printf("B_START: start time: %lld\n", fStartTime);
media_timed_event firstBufferEvent(fStartTime,
media_timed_event firstBufferEvent(
fStartTime - fSupplier->InitialLatency(),
BTimedEventQueue::B_HANDLE_BUFFER);
EventQueue()->AddEvent(firstBufferEvent);
}
@@ -607,7 +621,7 @@ printf("B_START: start time: %lld\n", fStartTime);
case BTimedEventQueue::B_STOP:
TRACE("AudioProducer::HandleEvent(B_STOP)\n");
EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true,
BTimedEventQueue::B_HANDLE_BUFFER);
BTimedEventQueue::B_HANDLE_BUFFER);
TRACE("AudioProducer::HandleEvent(B_STOP) done\n");
break;
@@ -633,10 +647,10 @@ printf("B_START: start time: %lld\n", fStartTime);
/ (sampleSize * fOutput.format.u.raw_audio.channel_count);
fFramesSent += nFrames;
bigtime_t nextEvent = fStartTime
fNextScheduledBuffer = fStartTime
+ bigtime_t(double(fFramesSent) * 1000000.0
/ double(fOutput.format.u.raw_audio.frame_rate));
media_timed_event nextBufferEvent(nextEvent,
/ double(fOutput.format.u.raw_audio.frame_rate));
media_timed_event nextBufferEvent(fNextScheduledBuffer,
BTimedEventQueue::B_HANDLE_BUFFER);
EventQueue()->AddEvent(nextBufferEvent);
} else {
@@ -663,7 +677,8 @@ AudioProducer::ChangeFormat(media_format* format)
{
TRACE("AudioProducer::ChangeFormat()\n");
format->u.raw_audio.buffer_size = media_raw_audio_format::wildcard.buffer_size;
format->u.raw_audio.buffer_size
= media_raw_audio_format::wildcard.buffer_size;
status_t ret = _SpecializeFormat(format);
if (ret != B_OK) {
@@ -677,7 +692,8 @@ AudioProducer::ChangeFormat(media_format* format)
return ret;
}
ret = BBufferProducer::ChangeFormat(fOutput.source, fOutput.destination, format);
ret = BBufferProducer::ChangeFormat(fOutput.source, fOutput.destination,
format);
if (ret != B_OK) {
TRACE(" ChangeFormat(): %s\n", strerror(ret));
return ret;
@@ -707,20 +723,20 @@ AudioProducer::_SpecializeFormat(media_format* format)
}
if (format->u.raw_audio.channel_count
== media_raw_audio_format::wildcard.channel_count) {
== media_raw_audio_format::wildcard.channel_count) {
format->u.raw_audio.channel_count = 2;
TRACE(" -> adjusting channel count, it was wildcard\n");
}
if (format->u.raw_audio.frame_rate
== media_raw_audio_format::wildcard.frame_rate) {
== media_raw_audio_format::wildcard.frame_rate) {
format->u.raw_audio.frame_rate = 44100.0;
TRACE(" -> adjusting frame rate, it was wildcard\n");
}
// check the buffer size, which may still be wildcarded
if (format->u.raw_audio.buffer_size
== media_raw_audio_format::wildcard.buffer_size) {
== media_raw_audio_format::wildcard.buffer_size) {
// pick something comfortable to suggest
TRACE(" -> adjusting buffer size, it was wildcard\n");
@@ -734,7 +750,6 @@ AudioProducer::_SpecializeFormat(media_format* format)
if (!fLowLatency)
format->u.raw_audio.buffer_size *= 3;
}
return B_OK;
@@ -794,9 +809,9 @@ AudioProducer::_FillNextBuffer(bigtime_t eventTime)
// number of sample in the buffer
// fill in the buffer header
media_header* hdr = buffer->Header();
hdr->type = B_MEDIA_RAW_AUDIO;
hdr->time_source = TimeSource()->ID();
media_header* header = buffer->Header();
header->type = B_MEDIA_RAW_AUDIO;
header->time_source = TimeSource()->ID();
buffer->SetSizeUsed(fOutput.format.u.raw_audio.buffer_size);
bigtime_t performanceTime = bigtime_t(double(fFramesSent)
@@ -817,9 +832,9 @@ AudioProducer::_FillNextBuffer(bigtime_t eventTime)
// stamp buffer
if (RunMode() == B_RECORDING) {
hdr->start_time = eventTime;
header->start_time = eventTime;
} else {
hdr->start_time = fStartTime + performanceTime;
header->start_time = fStartTime + performanceTime;
}
#if DEBUG_TO_FILE
@@ -8,10 +8,11 @@
#ifndef AUDIO_PRODUCER_H
#define AUDIO_PRODUCER_H
#include <BufferProducer.h>
//#include <Controllable.h>
#include <MediaEventLooper.h>
class AudioSupplier;
class BHandler;
@@ -19,6 +20,7 @@ enum {
MSG_PEAK_NOTIFICATION = 'pknt'
};
class AudioProducer : public BBufferProducer, public BMediaEventLooper {
public:
AudioProducer(const char* name,
@@ -116,6 +118,8 @@ private:
bool fUsingOurBuffers;
bigtime_t fLatency;
bigtime_t fInternalLatency;
bigtime_t fLastLateNotice;
bigtime_t fNextScheduledBuffer;
bool fLowLatency;
media_output fOutput;
bool fOutputEnabled;
@@ -18,6 +18,7 @@ public:
void SetFormat(const media_format& format);
const media_format& Format() const;
virtual bigtime_t InitialLatency() const = 0;
virtual status_t Read(void* buffer, int64 pos, int64 frames) = 0;
void SetOutOffset(int64 offset);
@@ -1,7 +1,9 @@
/*
* Copyright © 2000-2006 Ingo Weinhold <ingo_weinhold@gmx.de>
* Copyright 2000-2006 Ingo Weinhold <ingo_weinhold@gmx.de>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#include "AudioResampler.h"
#include <stdio.h>
@@ -11,39 +13,12 @@
//#define TRACE_AUDIO_RESAMPLER
#ifdef TRACE_AUDIO_RESAMPLER
# define TRACE(x...) printf(x)
# define TRACE(x...) printf(x)
#else
# define TRACE(x...)
# define TRACE(x...)
#endif
AudioResampler::AudioResampler()
: AudioReader(),
fSource(NULL),
fTimeScale(1.0),
fInOffset(0)
{
}
AudioResampler::AudioResampler(AudioReader* source, float frameRate,
float timeScale)
: AudioReader(),
fSource(NULL),
fTimeScale(timeScale),
fInOffset(0)
{
SetSource(source);
if (fSource)
fFormat.u.raw_audio.frame_rate = frameRate;
}
AudioResampler::~AudioResampler()
{
}
//! Calculates the greatest common divider of /a/ and /b/.
template<typename T> inline
T
@@ -92,6 +67,45 @@ resample_linear(void* _inBuffer, void* _outBuffer, uint32 channelCount,
}
// #pragma mark -
AudioResampler::AudioResampler()
:
AudioReader(),
fSource(NULL),
fTimeScale(1.0),
fInOffset(0)
{
}
AudioResampler::AudioResampler(AudioReader* source, float frameRate,
float timeScale)
:
AudioReader(),
fSource(NULL),
fTimeScale(timeScale),
fInOffset(0)
{
SetSource(source);
if (fSource)
fFormat.u.raw_audio.frame_rate = frameRate;
}
AudioResampler::~AudioResampler()
{
}
bigtime_t
AudioResampler::InitialLatency() const
{
return fSource->InitialLatency();
}
status_t
AudioResampler::Read(void* buffer, int64 pos, int64 frames)
{
@@ -185,7 +199,7 @@ AudioResampler::SetSource(AudioReader* source)
TRACE("AudioResampler::SetSource() - NULL source\n");
return;
}
if (source->Format().type != B_MEDIA_RAW_AUDIO) {
TRACE("AudioResampler::SetSource() - not B_MEDIA_RAW_AUDIO\n");
return;
@@ -197,7 +211,7 @@ AudioResampler::SetSource(AudioReader* source)
TRACE("AudioResampler::SetSource() - not host byte order\n");
return;
}
float frameRate = FrameRate();
// don't overwrite previous audio frame rate
fSource = source;
@@ -1,7 +1,10 @@
/*
* Copyright © 2000-2006 Ingo Weinhold <ingo_weinhold@gmx.de>
* Copyright 2000-2006 Ingo Weinhold <ingo_weinhold@gmx.de>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#ifndef AUDIO_RESAMPLER_H
#define AUDIO_RESAMPLER_H
/*! This AudioReader does both resampling an audio source to a different
sample rate and rescaling the time, e.g. it is possible to convert the
@@ -9,11 +12,10 @@
(time scale = -2).
*/
#ifndef AUDIO_RESAMPLER_H
#define AUDIO_RESAMPLER_H
#include "AudioReader.h"
class AudioResampler : public AudioReader {
public:
AudioResampler();
@@ -21,6 +23,7 @@ public:
float frameRate, float timeScale = 1.0);
virtual ~AudioResampler();
virtual bigtime_t InitialLatency() const;
virtual status_t Read(void* buffer, int64 pos, int64 frames);
virtual status_t InitCheck() const;
@@ -1,6 +1,8 @@
/* Copyright (c) 2000-2008, Ingo Weinhold <[email protected]>,
/* Copyright 2000-2008, Ingo Weinhold <[email protected]>,
* All Rights Reserved. Distributed under the terms of the MIT license.
*/
#include "AudioSupplier.h"
#include "AudioProducer.h"
@@ -26,6 +28,6 @@ AudioSupplier::SetAudioProducer(AudioProducer* producer)
status_t
AudioSupplier::InitCheck() const
{
return (fAudioProducer ? B_OK : B_NO_INIT);
return fAudioProducer ? B_OK : B_NO_INIT;
}
@@ -1,11 +1,12 @@
/* Copyright (c) 2000-2008, Ingo Weinhold <[email protected]>,
/* Copyright 2000-2008, Ingo Weinhold <[email protected]>,
* All Rights Reserved. Distributed under the terms of the MIT license.
*/
#ifndef AUDIO_SUPPLIER_H
#define AUDIO_SUPPLIER_H
/*! This class is an interface used by the AudioProducer to retreive the
audio data to be played. */
#ifndef AUDIO_SUPPLIER_H
#define AUDIO_SUPPLIER_H
#include <MediaDefs.h>
@@ -14,21 +15,23 @@
class AudioProducer;
class AudioSupplier {
public:
public:
AudioSupplier();
virtual ~AudioSupplier();
virtual void SetAudioProducer(AudioProducer* producer);
virtual status_t InitCheck() const;
virtual bigtime_t InitialLatency() const = 0;
virtual status_t GetFrames(void* buffer, int64 frameCount,
bigtime_t startTime,
bigtime_t endTime) = 0;
virtual void SetFormat(const media_format& format) = 0;
virtual status_t InitCheck() const;
protected:
protected:
AudioProducer* fAudioProducer;
};
@@ -1,8 +1,9 @@
/*
* Copyright © 2008 Stephan Aßmus <superstippi@gmx.de>
* Copyright 2008 Stephan Aßmus <superstippi@gmx.de>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#include "AudioVolumeConverter.h"
#include <stdio.h>
@@ -13,31 +14,12 @@
//#define TRACE_AUDIO_CONVERTER
#ifdef TRACE_AUDIO_CONVERTER
# define TRACE(x...) printf(x)
# define TRACE(x...) printf(x)
#else
# define TRACE(x...)
# define TRACE(x...)
#endif
AudioVolumeConverter::AudioVolumeConverter(AudioReader* source, float volume)
: AudioReader(),
fSource(NULL),
fVolume(volume),
fPreviousVolume(volume)
{
if (source && source->Format().type == B_MEDIA_RAW_AUDIO)
fFormat = source->Format();
else
source = NULL;
fSource = source;
}
AudioVolumeConverter::~AudioVolumeConverter()
{
}
template<typename SampleType>
static void
convert(SampleType* buffer, const int32 samples, const float volume,
@@ -66,6 +48,36 @@ convert(SampleType* buffer, const int32 frames, const int32 channels,
}
// #pragma mark -
AudioVolumeConverter::AudioVolumeConverter(AudioReader* source, float volume)
:
AudioReader(),
fSource(NULL),
fVolume(volume),
fPreviousVolume(volume)
{
if (source && source->Format().type == B_MEDIA_RAW_AUDIO)
fFormat = source->Format();
else
source = NULL;
fSource = source;
}
AudioVolumeConverter::~AudioVolumeConverter()
{
}
bigtime_t
AudioVolumeConverter::InitialLatency() const
{
return fSource->InitialLatency();
}
status_t
AudioVolumeConverter::Read(void* buffer, int64 pos, int64 frames)
{
@@ -1,23 +1,26 @@
/*
* Copyright © 2008 Stephan Aßmus <superstippi@gmx.de>
* Copyright 2008 Stephan Aßmus <superstippi@gmx.de>
* All rights reserved. Distributed under the terms of the MIT licensce.
*/
#ifndef AUDIO_VOLUME_CONVERTER_H
#define AUDIO_VOLUME_CONVERTER_H
/*! This AudioReader just filters the volume. It depends on floating point
* audio format.
*/
#ifndef AUDIO_VOLUME_CONVERTER_H
#define AUDIO_VOLUME_CONVERTER_H
#include "AudioReader.h"
class AudioVolumeConverter : public AudioReader {
public:
AudioVolumeConverter(AudioReader* source,
float volume = 1.0);
virtual ~AudioVolumeConverter();
virtual bigtime_t InitialLatency() const;
virtual status_t Read(void* buffer, int64 pos, int64 frames);
virtual status_t InitCheck() const;
@@ -115,7 +115,14 @@ MediaTrackAudioSupplier::Duration() const
// #pragma mark - AudioReader
// Read
bigtime_t
MediaTrackAudioSupplier::InitialLatency() const
{
// TODO: this is just a wild guess, and not really founded on anything.
return 100000;
}
status_t
MediaTrackAudioSupplier::Read(void* buffer, int64 pos, int64 frames)
{
@@ -518,15 +525,15 @@ MediaTrackAudioSupplier::_ReadCachedFrames(void*& dest, int64& pos,
}
}
// _ReadUncachedFrames
//
// Reads /frames/ frames from /position/ into /buffer/. The frames are not
// read from the cache, but read frames are cached, if possible.
// New cache buffers are stamped with the supplied time.
// If an error occurs, the untouched part of the buffer is set to 0.
/*! Reads /frames/ frames from /position/ into /buffer/. The frames are not
read from the cache, but read frames are cached, if possible.
New cache buffers are stamped with the supplied time.
If an error occurs, the untouched part of the buffer is set to 0.
*/
status_t
MediaTrackAudioSupplier::_ReadUncachedFrames(void* buffer, int64 position,
int64 frames, bigtime_t time)
int64 frames, bigtime_t time)
{
TRACE("_ReadUncachedFrames()\n");
status_t error = B_OK;
@@ -1,21 +1,24 @@
/*
* Copyright © 2000-2004 Ingo Weinhold <ingo_weinhold@gmx.de>
* Copyright © 2006-2008 Stephan Aßmus <superstippi@gmx.de>
* Copyright 2000-2004 Ingo Weinhold <ingo_weinhold@gmx.de>
* Copyright 2006-2008 Stephan Aßmus <superstippi@gmx.de>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef MEDIA_TRACK_AUDIO_SUPPLIER_H
#define MEDIA_TRACK_AUDIO_SUPPLIER_H
#include <List.h>
#include "AudioTrackSupplier.h"
class BMediaTrack;
struct media_codec_info;
struct media_format;
class MediaTrackAudioSupplier : public AudioTrackSupplier {
public:
public:
MediaTrackAudioSupplier(BMediaTrack* track,
int32 trackIndex);
virtual ~MediaTrackAudioSupplier();
@@ -27,6 +30,7 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier {
// AudioReader interface
// (needed to reuse the class as AudioResampler input)
virtual bigtime_t InitialLatency() const;
virtual status_t Read(void* buffer, int64 pos, int64 frames);
virtual status_t InitCheck() const;
@@ -34,7 +38,7 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier {
virtual int32 TrackIndex() const
{ return fTrackIndex; }
private:
private:
struct Buffer;
void _InitFromTrack();
@@ -1,7 +1,9 @@
/*
* Copyright © 2008 Stephan Aßmus <superstippi@gmx.de>
/*
* Copyright 2008 Stephan Aßmus <superstippi@gmx.de>
* All Rights Reserved. Distributed under the terms of the MIT license.
*/
#include "ProxyAudioSupplier.h"
#include <algorithm>
@@ -33,8 +35,9 @@ using std::swap;
struct PlayingInterval {
PlayingInterval(bigtime_t startTime, bigtime_t endTime)
: start_time(startTime)
, end_time(endTime)
:
start_time(startTime),
end_time(endTime)
{
}
@@ -47,16 +50,17 @@ struct PlayingInterval {
ProxyAudioSupplier::ProxyAudioSupplier(PlaybackManager* playbackManager)
: fSupplierLock("audio supplier lock")
:
fSupplierLock("audio supplier lock"),
, fPlaybackManager(playbackManager)
, fVideoFrameRate(25.0)
, fVolume(1.0)
fPlaybackManager(playbackManager),
fVideoFrameRate(25.0),
fVolume(1.0),
, fSupplier(NULL)
, fAdapter(NULL)
, fVolumeConverter(NULL)
, fAudioResampler()
fSupplier(NULL),
fAdapter(NULL),
fVolumeConverter(NULL),
fAudioResampler()
{
TRACE("ProxyAudioSupplier()\n");
}
@@ -70,6 +74,18 @@ ProxyAudioSupplier::~ProxyAudioSupplier()
}
bigtime_t
ProxyAudioSupplier::InitialLatency() const
{
BAutolock _(fSupplierLock);
if (fSupplier == NULL)
return 0;
return fSupplier->InitialLatency();
}
status_t
ProxyAudioSupplier::GetFrames(void* buffer, int64 frameCount,
bigtime_t startTime, bigtime_t endTime)
@@ -100,7 +116,7 @@ ProxyAudioSupplier::GetFrames(void* buffer, int64 frameCount,
ERROR("GetFrames() - zero duration audio interval! start "
"time: %lld\n", intervalStartTime);
break;
}
}
if (!playingIntervals.AddItem(interval)) {
delete interval;
error = B_NO_MEMORY;
@@ -182,7 +198,7 @@ ProxyAudioSupplier::SetFormat(const media_format& format)
{
//printf("ProxyAudioSupplier::SetFormat()\n");
#ifdef TRACE_PROXY_AUDIO_SUPPLIER
char string[256];
char string[256];
string_for_format(format, string, 256);
TRACE("SetFormat(%s)\n", string);
#endif
@@ -258,6 +274,7 @@ ProxyAudioSupplier::Volume()
// #pragma mark - audio/video/frame/time conversion
int64
ProxyAudioSupplier::_AudioFrameForVideoFrame(int64 frame) const
{
@@ -1,10 +1,11 @@
/*
* Copyright © 2008 Stephan Aßmus <superstippi@gmx.de>
* Copyright 2008 Stephan Aßmus <superstippi@gmx.de>
* All Rights Reserved. Distributed under the terms of the MIT license.
*/
#ifndef PROXY_AUDIO_SUPPLIER_H
#define PROXY_AUDIO_SUPPLIER_H
#include <Locker.h>
#include "AudioResampler.h"
@@ -26,6 +27,7 @@ public:
virtual status_t GetFrames(void* buffer, int64 frameCount,
bigtime_t startTime, bigtime_t endTime);
virtual bigtime_t InitialLatency() const;
virtual void SetFormat(const media_format& format);
virtual const media_format& Format() const;
@@ -49,16 +51,16 @@ private:
void* _SkipFrames(void* buffer, int64 frames) const;
private:
BLocker fSupplierLock;
mutable BLocker fSupplierLock;
PlaybackManager* fPlaybackManager;
float fVideoFrameRate;
float fVolume;
PlaybackManager* fPlaybackManager;
float fVideoFrameRate;
float fVolume;
AudioTrackSupplier* fSupplier;
AudioReader* fAdapter;
AudioVolumeConverter* fVolumeConverter;
AudioResampler fAudioResampler;
AudioTrackSupplier* fSupplier;
AudioReader* fAdapter;
AudioVolumeConverter* fVolumeConverter;
AudioResampler fAudioResampler;
};