* 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:
@@ -77,6 +77,13 @@ AudioAdapter::~AudioAdapter()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
AudioAdapter::InitialLatency() const
|
||||||
|
{
|
||||||
|
return fSource->InitialLatency();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AudioAdapter::Read(void* buffer, int64 pos, int64 frames)
|
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.
|
* 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
|
/*! This AudioReader slaves an AudioConverter and an AudioResampler
|
||||||
to convert the source data to a given format.
|
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.
|
If input and output format are the same, the overhead is quit small.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AUDIO_ADAPTER_H
|
|
||||||
#define AUDIO_ADAPTER_H
|
|
||||||
|
|
||||||
#include "AudioReader.h"
|
#include "AudioReader.h"
|
||||||
|
|
||||||
|
|
||||||
class AudioChannelConverter;
|
class AudioChannelConverter;
|
||||||
class AudioFormatConverter;
|
class AudioFormatConverter;
|
||||||
class AudioResampler;
|
class AudioResampler;
|
||||||
|
|
||||||
|
|
||||||
class AudioAdapter : public AudioReader {
|
class AudioAdapter : public AudioReader {
|
||||||
public:
|
public:
|
||||||
AudioAdapter(AudioReader* source,
|
AudioAdapter(AudioReader* source,
|
||||||
const media_format& format);
|
const media_format& format);
|
||||||
virtual ~AudioAdapter();
|
virtual ~AudioAdapter();
|
||||||
|
|
||||||
|
virtual bigtime_t InitialLatency() const;
|
||||||
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
||||||
|
|
||||||
virtual status_t InitCheck() const;
|
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.
|
* All rights reserved. Distributed under the terms of the MIT licensce.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "AudioChannelConverter.h"
|
#include "AudioChannelConverter.h"
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
@@ -10,29 +12,15 @@
|
|||||||
|
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_AUDIO_CONVERTER
|
//#define TRACE_AUDIO_CONVERTER
|
||||||
#ifdef TRACE_AUDIO_CONVERTER
|
#ifdef TRACE_AUDIO_CONVERTER
|
||||||
# define TRACE(x...) printf(x)
|
# define TRACE(x...) printf(x)
|
||||||
#else
|
#else
|
||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
#endif
|
#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>
|
template<typename Type, typename BigType>
|
||||||
static void
|
static void
|
||||||
convert(Type* inBuffer, Type* outBuffer, int32 inChannels, int32 outChannels,
|
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
|
status_t
|
||||||
AudioChannelConverter::Read(void* outBuffer, int64 pos, int64 frames)
|
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.
|
* 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
|
/*! This AudioReader just converts the source channel count
|
||||||
into another one, e.g. 1 -> 2. Frame rate and sample format
|
into another one, e.g. 1 -> 2. Frame rate and sample format
|
||||||
remain unchanged.
|
remain unchanged.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AUDIO_CHANNEL_CONVERTER_H
|
|
||||||
#define AUDIO_CHANNEL_CONVERTER_H
|
|
||||||
|
|
||||||
#include "AudioReader.h"
|
#include "AudioReader.h"
|
||||||
|
|
||||||
|
|
||||||
class AudioChannelConverter : public AudioReader {
|
class AudioChannelConverter : public AudioReader {
|
||||||
public:
|
public:
|
||||||
AudioChannelConverter(AudioReader* source,
|
AudioChannelConverter(AudioReader* source,
|
||||||
const media_format& format);
|
const media_format& format);
|
||||||
virtual ~AudioChannelConverter();
|
virtual ~AudioChannelConverter();
|
||||||
|
|
||||||
|
virtual bigtime_t InitialLatency() const;
|
||||||
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
||||||
|
|
||||||
virtual status_t InitCheck() const;
|
virtual status_t InitCheck() const;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2000-2006 Ingo Weinhold <[email protected]>
|
* Copyright 2000-2006 Ingo Weinhold <[email protected]>
|
||||||
* 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.
|
* All rights reserved. Distributed under the terms of the MIT licensce.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "AudioFormatConverter.h"
|
#include "AudioFormatConverter.h"
|
||||||
|
|
||||||
#include <ByteOrder.h>
|
#include <ByteOrder.h>
|
||||||
@@ -12,44 +13,12 @@
|
|||||||
|
|
||||||
//#define TRACE_AUDIO_CONVERTER
|
//#define TRACE_AUDIO_CONVERTER
|
||||||
#ifdef TRACE_AUDIO_CONVERTER
|
#ifdef TRACE_AUDIO_CONVERTER
|
||||||
# define TRACE(x...) printf(x)
|
# define TRACE(x...) printf(x)
|
||||||
#else
|
#else
|
||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
#endif
|
#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 {
|
struct ReadFloat {
|
||||||
inline int operator()(const void* buffer) const {
|
inline int operator()(const void* buffer) const {
|
||||||
// 0 == mid, -1.0 == bottom, 1.0 == top
|
// 0 == mid, -1.0 == bottom, 1.0 == top
|
||||||
@@ -150,8 +119,7 @@ convert(const ReadT& read, const WriteT& write,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static void
|
||||||
void
|
|
||||||
swap_sample_byte_order(void* buffer, uint32 format, size_t length)
|
swap_sample_byte_order(void* buffer, uint32 format, size_t length)
|
||||||
{
|
{
|
||||||
type_code type = B_ANY_TYPE;
|
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
|
status_t
|
||||||
AudioFormatConverter::Read(void* buffer, int64 pos, int64 frames)
|
AudioFormatConverter::Read(void* buffer, int64 pos, int64 frames)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,25 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2000-2006 Ingo Weinhold <[email protected]>
|
* Copyright 2000-2006 Ingo Weinhold <[email protected]>
|
||||||
* 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.
|
* 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)
|
/*! This AudioReader just converts the source sample format (and byte order)
|
||||||
into another one, e.g. LE short -> BE float. Frame rate and channel
|
into another one, e.g. LE short -> BE float. Frame rate and channel
|
||||||
count remain unchanged.
|
count remain unchanged.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AUDIO_FORMAT_CONVERTER_H
|
|
||||||
#define AUDIO_FORMAT_CONVERTER_H
|
|
||||||
|
|
||||||
#include "AudioReader.h"
|
#include "AudioReader.h"
|
||||||
|
|
||||||
|
|
||||||
class AudioFormatConverter : public AudioReader {
|
class AudioFormatConverter : public AudioReader {
|
||||||
public:
|
public:
|
||||||
AudioFormatConverter(AudioReader* source,
|
AudioFormatConverter(AudioReader* source,
|
||||||
uint32 format, uint32 byte_order);
|
uint32 format, uint32 byte_order);
|
||||||
virtual ~AudioFormatConverter();
|
virtual ~AudioFormatConverter();
|
||||||
|
|
||||||
|
virtual bigtime_t InitialLatency() const;
|
||||||
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
||||||
|
|
||||||
virtual status_t InitCheck() const;
|
virtual status_t InitCheck() const;
|
||||||
|
|||||||
@@ -37,13 +37,13 @@
|
|||||||
// debugging
|
// debugging
|
||||||
//#define TRACE_AUDIO_PRODUCER
|
//#define TRACE_AUDIO_PRODUCER
|
||||||
#ifdef TRACE_AUDIO_PRODUCER
|
#ifdef TRACE_AUDIO_PRODUCER
|
||||||
# define TRACE(x...) printf(x)
|
# define TRACE(x...) printf(x)
|
||||||
# define TRACE_BUFFER(x...)
|
# define TRACE_BUFFER(x...)
|
||||||
# define ERROR(x...) fprintf(stderr, x)
|
# define ERROR(x...) fprintf(stderr, x)
|
||||||
#else
|
#else
|
||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
# define TRACE_BUFFER(x...)
|
# define TRACE_BUFFER(x...)
|
||||||
# define ERROR(x...) fprintf(stderr, x)
|
# define ERROR(x...) fprintf(stderr, x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -85,24 +85,63 @@ init_media_file(media_format format, BMediaTrack** _track)
|
|||||||
#endif // DEBUG_TO_FILE
|
#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,
|
AudioProducer::AudioProducer(const char* name, AudioSupplier* supplier,
|
||||||
bool lowLatency)
|
bool lowLatency)
|
||||||
: BMediaNode(name),
|
:
|
||||||
BBufferProducer(B_MEDIA_RAW_AUDIO),
|
BMediaNode(name),
|
||||||
BMediaEventLooper(),
|
BBufferProducer(B_MEDIA_RAW_AUDIO),
|
||||||
|
BMediaEventLooper(),
|
||||||
|
|
||||||
fBufferGroup(NULL),
|
fBufferGroup(NULL),
|
||||||
fLatency(0),
|
fLatency(0),
|
||||||
fInternalLatency(0),
|
fInternalLatency(0),
|
||||||
fLowLatency(lowLatency),
|
fLastLateNotice(0),
|
||||||
fOutputEnabled(true),
|
fNextScheduledBuffer(0),
|
||||||
fFramesSent(0),
|
fLowLatency(lowLatency),
|
||||||
fStartTime(0),
|
fOutputEnabled(true),
|
||||||
fSupplier(supplier),
|
fFramesSent(0),
|
||||||
|
fStartTime(0),
|
||||||
|
fSupplier(supplier),
|
||||||
|
|
||||||
fPeakListener(NULL)
|
fPeakListener(NULL)
|
||||||
{
|
{
|
||||||
TRACE("%p->AudioProducer::AudioProducer(%s, %p, %d)\n", this, name,
|
TRACE("%p->AudioProducer::AudioProducer(%s, %p, %d)\n", this, name,
|
||||||
supplier, lowLatency);
|
supplier, lowLatency);
|
||||||
@@ -135,9 +174,11 @@ AudioProducer::AudioProducer(const char* name, AudioSupplier* supplier,
|
|||||||
// we're not connected yet
|
// we're not connected yet
|
||||||
fOutput.destination = media_destination::null;
|
fOutput.destination = media_destination::null;
|
||||||
fOutput.format = fPreferredFormat;
|
fOutput.format = fPreferredFormat;
|
||||||
|
|
||||||
// init the audio supplier
|
// init the audio supplier
|
||||||
if (fSupplier) {
|
if (fSupplier != NULL) {
|
||||||
fSupplier->SetAudioProducer(this);
|
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
|
void
|
||||||
AudioProducer::Connect(status_t error, const media_source& source,
|
AudioProducer::Connect(status_t error, const media_source& source,
|
||||||
const media_destination& destination, const media_format& format,
|
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
|
// If we're late, we need to catch up. Respond in a manner appropriate
|
||||||
// to our current run mode.
|
// to our current run mode.
|
||||||
if (what == fOutput.source) {
|
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) {
|
if (RunMode() == B_RECORDING) {
|
||||||
// ...
|
// ...
|
||||||
} else if (RunMode() == B_INCREASE_LATENCY) {
|
} 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");
|
TRACE("AudioProducer::HandleEvent(B_START)\n");
|
||||||
if (RunState() != B_STARTED) {
|
if (RunState() != B_STARTED) {
|
||||||
fFramesSent = 0;
|
fFramesSent = 0;
|
||||||
fStartTime = event->event_time;
|
fStartTime = event->event_time + fSupplier->InitialLatency();
|
||||||
printf("B_START: start time: %lld\n", fStartTime);
|
printf("B_START: start time: %lld\n", fStartTime);
|
||||||
media_timed_event firstBufferEvent(fStartTime,
|
media_timed_event firstBufferEvent(
|
||||||
|
fStartTime - fSupplier->InitialLatency(),
|
||||||
BTimedEventQueue::B_HANDLE_BUFFER);
|
BTimedEventQueue::B_HANDLE_BUFFER);
|
||||||
EventQueue()->AddEvent(firstBufferEvent);
|
EventQueue()->AddEvent(firstBufferEvent);
|
||||||
}
|
}
|
||||||
@@ -607,7 +621,7 @@ printf("B_START: start time: %lld\n", fStartTime);
|
|||||||
case BTimedEventQueue::B_STOP:
|
case BTimedEventQueue::B_STOP:
|
||||||
TRACE("AudioProducer::HandleEvent(B_STOP)\n");
|
TRACE("AudioProducer::HandleEvent(B_STOP)\n");
|
||||||
EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true,
|
EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true,
|
||||||
BTimedEventQueue::B_HANDLE_BUFFER);
|
BTimedEventQueue::B_HANDLE_BUFFER);
|
||||||
TRACE("AudioProducer::HandleEvent(B_STOP) done\n");
|
TRACE("AudioProducer::HandleEvent(B_STOP) done\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -633,10 +647,10 @@ printf("B_START: start time: %lld\n", fStartTime);
|
|||||||
/ (sampleSize * fOutput.format.u.raw_audio.channel_count);
|
/ (sampleSize * fOutput.format.u.raw_audio.channel_count);
|
||||||
fFramesSent += nFrames;
|
fFramesSent += nFrames;
|
||||||
|
|
||||||
bigtime_t nextEvent = fStartTime
|
fNextScheduledBuffer = fStartTime
|
||||||
+ bigtime_t(double(fFramesSent) * 1000000.0
|
+ bigtime_t(double(fFramesSent) * 1000000.0
|
||||||
/ double(fOutput.format.u.raw_audio.frame_rate));
|
/ double(fOutput.format.u.raw_audio.frame_rate));
|
||||||
media_timed_event nextBufferEvent(nextEvent,
|
media_timed_event nextBufferEvent(fNextScheduledBuffer,
|
||||||
BTimedEventQueue::B_HANDLE_BUFFER);
|
BTimedEventQueue::B_HANDLE_BUFFER);
|
||||||
EventQueue()->AddEvent(nextBufferEvent);
|
EventQueue()->AddEvent(nextBufferEvent);
|
||||||
} else {
|
} else {
|
||||||
@@ -663,7 +677,8 @@ AudioProducer::ChangeFormat(media_format* format)
|
|||||||
{
|
{
|
||||||
TRACE("AudioProducer::ChangeFormat()\n");
|
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);
|
status_t ret = _SpecializeFormat(format);
|
||||||
if (ret != B_OK) {
|
if (ret != B_OK) {
|
||||||
@@ -677,7 +692,8 @@ AudioProducer::ChangeFormat(media_format* format)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = BBufferProducer::ChangeFormat(fOutput.source, fOutput.destination, format);
|
ret = BBufferProducer::ChangeFormat(fOutput.source, fOutput.destination,
|
||||||
|
format);
|
||||||
if (ret != B_OK) {
|
if (ret != B_OK) {
|
||||||
TRACE(" ChangeFormat(): %s\n", strerror(ret));
|
TRACE(" ChangeFormat(): %s\n", strerror(ret));
|
||||||
return ret;
|
return ret;
|
||||||
@@ -707,20 +723,20 @@ AudioProducer::_SpecializeFormat(media_format* format)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (format->u.raw_audio.channel_count
|
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;
|
format->u.raw_audio.channel_count = 2;
|
||||||
TRACE(" -> adjusting channel count, it was wildcard\n");
|
TRACE(" -> adjusting channel count, it was wildcard\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format->u.raw_audio.frame_rate
|
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;
|
format->u.raw_audio.frame_rate = 44100.0;
|
||||||
TRACE(" -> adjusting frame rate, it was wildcard\n");
|
TRACE(" -> adjusting frame rate, it was wildcard\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the buffer size, which may still be wildcarded
|
// check the buffer size, which may still be wildcarded
|
||||||
if (format->u.raw_audio.buffer_size
|
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
|
// pick something comfortable to suggest
|
||||||
TRACE(" -> adjusting buffer size, it was wildcard\n");
|
TRACE(" -> adjusting buffer size, it was wildcard\n");
|
||||||
|
|
||||||
@@ -734,7 +750,6 @@ AudioProducer::_SpecializeFormat(media_format* format)
|
|||||||
|
|
||||||
if (!fLowLatency)
|
if (!fLowLatency)
|
||||||
format->u.raw_audio.buffer_size *= 3;
|
format->u.raw_audio.buffer_size *= 3;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -794,9 +809,9 @@ AudioProducer::_FillNextBuffer(bigtime_t eventTime)
|
|||||||
// number of sample in the buffer
|
// number of sample in the buffer
|
||||||
|
|
||||||
// fill in the buffer header
|
// fill in the buffer header
|
||||||
media_header* hdr = buffer->Header();
|
media_header* header = buffer->Header();
|
||||||
hdr->type = B_MEDIA_RAW_AUDIO;
|
header->type = B_MEDIA_RAW_AUDIO;
|
||||||
hdr->time_source = TimeSource()->ID();
|
header->time_source = TimeSource()->ID();
|
||||||
buffer->SetSizeUsed(fOutput.format.u.raw_audio.buffer_size);
|
buffer->SetSizeUsed(fOutput.format.u.raw_audio.buffer_size);
|
||||||
|
|
||||||
bigtime_t performanceTime = bigtime_t(double(fFramesSent)
|
bigtime_t performanceTime = bigtime_t(double(fFramesSent)
|
||||||
@@ -817,9 +832,9 @@ AudioProducer::_FillNextBuffer(bigtime_t eventTime)
|
|||||||
|
|
||||||
// stamp buffer
|
// stamp buffer
|
||||||
if (RunMode() == B_RECORDING) {
|
if (RunMode() == B_RECORDING) {
|
||||||
hdr->start_time = eventTime;
|
header->start_time = eventTime;
|
||||||
} else {
|
} else {
|
||||||
hdr->start_time = fStartTime + performanceTime;
|
header->start_time = fStartTime + performanceTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_TO_FILE
|
#if DEBUG_TO_FILE
|
||||||
|
|||||||
@@ -8,10 +8,11 @@
|
|||||||
#ifndef AUDIO_PRODUCER_H
|
#ifndef AUDIO_PRODUCER_H
|
||||||
#define AUDIO_PRODUCER_H
|
#define AUDIO_PRODUCER_H
|
||||||
|
|
||||||
|
|
||||||
#include <BufferProducer.h>
|
#include <BufferProducer.h>
|
||||||
//#include <Controllable.h>
|
|
||||||
#include <MediaEventLooper.h>
|
#include <MediaEventLooper.h>
|
||||||
|
|
||||||
|
|
||||||
class AudioSupplier;
|
class AudioSupplier;
|
||||||
class BHandler;
|
class BHandler;
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ enum {
|
|||||||
MSG_PEAK_NOTIFICATION = 'pknt'
|
MSG_PEAK_NOTIFICATION = 'pknt'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class AudioProducer : public BBufferProducer, public BMediaEventLooper {
|
class AudioProducer : public BBufferProducer, public BMediaEventLooper {
|
||||||
public:
|
public:
|
||||||
AudioProducer(const char* name,
|
AudioProducer(const char* name,
|
||||||
@@ -116,6 +118,8 @@ private:
|
|||||||
bool fUsingOurBuffers;
|
bool fUsingOurBuffers;
|
||||||
bigtime_t fLatency;
|
bigtime_t fLatency;
|
||||||
bigtime_t fInternalLatency;
|
bigtime_t fInternalLatency;
|
||||||
|
bigtime_t fLastLateNotice;
|
||||||
|
bigtime_t fNextScheduledBuffer;
|
||||||
bool fLowLatency;
|
bool fLowLatency;
|
||||||
media_output fOutput;
|
media_output fOutput;
|
||||||
bool fOutputEnabled;
|
bool fOutputEnabled;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
void SetFormat(const media_format& format);
|
void SetFormat(const media_format& format);
|
||||||
const media_format& Format() const;
|
const media_format& Format() const;
|
||||||
|
|
||||||
|
virtual bigtime_t InitialLatency() const = 0;
|
||||||
virtual status_t Read(void* buffer, int64 pos, int64 frames) = 0;
|
virtual status_t Read(void* buffer, int64 pos, int64 frames) = 0;
|
||||||
|
|
||||||
void SetOutOffset(int64 offset);
|
void SetOutOffset(int64 offset);
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* 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.
|
* All rights reserved. Distributed under the terms of the MIT licensce.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "AudioResampler.h"
|
#include "AudioResampler.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -11,39 +13,12 @@
|
|||||||
|
|
||||||
//#define TRACE_AUDIO_RESAMPLER
|
//#define TRACE_AUDIO_RESAMPLER
|
||||||
#ifdef TRACE_AUDIO_RESAMPLER
|
#ifdef TRACE_AUDIO_RESAMPLER
|
||||||
# define TRACE(x...) printf(x)
|
# define TRACE(x...) printf(x)
|
||||||
#else
|
#else
|
||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
#endif
|
#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/.
|
//! Calculates the greatest common divider of /a/ and /b/.
|
||||||
template<typename T> inline
|
template<typename T> inline
|
||||||
T
|
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
|
status_t
|
||||||
AudioResampler::Read(void* buffer, int64 pos, int64 frames)
|
AudioResampler::Read(void* buffer, int64 pos, int64 frames)
|
||||||
{
|
{
|
||||||
@@ -185,7 +199,7 @@ AudioResampler::SetSource(AudioReader* source)
|
|||||||
TRACE("AudioResampler::SetSource() - NULL source\n");
|
TRACE("AudioResampler::SetSource() - NULL source\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source->Format().type != B_MEDIA_RAW_AUDIO) {
|
if (source->Format().type != B_MEDIA_RAW_AUDIO) {
|
||||||
TRACE("AudioResampler::SetSource() - not B_MEDIA_RAW_AUDIO\n");
|
TRACE("AudioResampler::SetSource() - not B_MEDIA_RAW_AUDIO\n");
|
||||||
return;
|
return;
|
||||||
@@ -197,7 +211,7 @@ AudioResampler::SetSource(AudioReader* source)
|
|||||||
TRACE("AudioResampler::SetSource() - not host byte order\n");
|
TRACE("AudioResampler::SetSource() - not host byte order\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float frameRate = FrameRate();
|
float frameRate = FrameRate();
|
||||||
// don't overwrite previous audio frame rate
|
// don't overwrite previous audio frame rate
|
||||||
fSource = source;
|
fSource = source;
|
||||||
|
|||||||
@@ -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.
|
* 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
|
/*! 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
|
sample rate and rescaling the time, e.g. it is possible to convert the
|
||||||
@@ -9,11 +12,10 @@
|
|||||||
(time scale = -2).
|
(time scale = -2).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AUDIO_RESAMPLER_H
|
|
||||||
#define AUDIO_RESAMPLER_H
|
|
||||||
|
|
||||||
#include "AudioReader.h"
|
#include "AudioReader.h"
|
||||||
|
|
||||||
|
|
||||||
class AudioResampler : public AudioReader {
|
class AudioResampler : public AudioReader {
|
||||||
public:
|
public:
|
||||||
AudioResampler();
|
AudioResampler();
|
||||||
@@ -21,6 +23,7 @@ public:
|
|||||||
float frameRate, float timeScale = 1.0);
|
float frameRate, float timeScale = 1.0);
|
||||||
virtual ~AudioResampler();
|
virtual ~AudioResampler();
|
||||||
|
|
||||||
|
virtual bigtime_t InitialLatency() const;
|
||||||
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
||||||
|
|
||||||
virtual status_t InitCheck() const;
|
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.
|
* All Rights Reserved. Distributed under the terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "AudioSupplier.h"
|
#include "AudioSupplier.h"
|
||||||
|
|
||||||
#include "AudioProducer.h"
|
#include "AudioProducer.h"
|
||||||
@@ -26,6 +28,6 @@ AudioSupplier::SetAudioProducer(AudioProducer* producer)
|
|||||||
status_t
|
status_t
|
||||||
AudioSupplier::InitCheck() const
|
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.
|
* 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
|
/*! This class is an interface used by the AudioProducer to retreive the
|
||||||
audio data to be played. */
|
audio data to be played. */
|
||||||
#ifndef AUDIO_SUPPLIER_H
|
|
||||||
#define AUDIO_SUPPLIER_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <MediaDefs.h>
|
#include <MediaDefs.h>
|
||||||
@@ -14,21 +15,23 @@
|
|||||||
class AudioProducer;
|
class AudioProducer;
|
||||||
|
|
||||||
class AudioSupplier {
|
class AudioSupplier {
|
||||||
public:
|
public:
|
||||||
AudioSupplier();
|
AudioSupplier();
|
||||||
virtual ~AudioSupplier();
|
virtual ~AudioSupplier();
|
||||||
|
|
||||||
virtual void SetAudioProducer(AudioProducer* producer);
|
virtual void SetAudioProducer(AudioProducer* producer);
|
||||||
|
|
||||||
|
virtual status_t InitCheck() const;
|
||||||
|
|
||||||
|
virtual bigtime_t InitialLatency() const = 0;
|
||||||
|
|
||||||
virtual status_t GetFrames(void* buffer, int64 frameCount,
|
virtual status_t GetFrames(void* buffer, int64 frameCount,
|
||||||
bigtime_t startTime,
|
bigtime_t startTime,
|
||||||
bigtime_t endTime) = 0;
|
bigtime_t endTime) = 0;
|
||||||
|
|
||||||
virtual void SetFormat(const media_format& format) = 0;
|
virtual void SetFormat(const media_format& format) = 0;
|
||||||
|
|
||||||
virtual status_t InitCheck() const;
|
protected:
|
||||||
|
|
||||||
protected:
|
|
||||||
AudioProducer* fAudioProducer;
|
AudioProducer* fAudioProducer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +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.
|
* All rights reserved. Distributed under the terms of the MIT licensce.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "AudioVolumeConverter.h"
|
#include "AudioVolumeConverter.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -13,31 +14,12 @@
|
|||||||
|
|
||||||
//#define TRACE_AUDIO_CONVERTER
|
//#define TRACE_AUDIO_CONVERTER
|
||||||
#ifdef TRACE_AUDIO_CONVERTER
|
#ifdef TRACE_AUDIO_CONVERTER
|
||||||
# define TRACE(x...) printf(x)
|
# define TRACE(x...) printf(x)
|
||||||
#else
|
#else
|
||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
#endif
|
#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>
|
template<typename SampleType>
|
||||||
static void
|
static void
|
||||||
convert(SampleType* buffer, const int32 samples, const float volume,
|
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
|
status_t
|
||||||
AudioVolumeConverter::Read(void* buffer, int64 pos, int64 frames)
|
AudioVolumeConverter::Read(void* buffer, int64 pos, int64 frames)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* 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.
|
* 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
|
/*! This AudioReader just filters the volume. It depends on floating point
|
||||||
* audio format.
|
* audio format.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AUDIO_VOLUME_CONVERTER_H
|
|
||||||
#define AUDIO_VOLUME_CONVERTER_H
|
|
||||||
|
|
||||||
#include "AudioReader.h"
|
#include "AudioReader.h"
|
||||||
|
|
||||||
|
|
||||||
class AudioVolumeConverter : public AudioReader {
|
class AudioVolumeConverter : public AudioReader {
|
||||||
public:
|
public:
|
||||||
AudioVolumeConverter(AudioReader* source,
|
AudioVolumeConverter(AudioReader* source,
|
||||||
float volume = 1.0);
|
float volume = 1.0);
|
||||||
virtual ~AudioVolumeConverter();
|
virtual ~AudioVolumeConverter();
|
||||||
|
|
||||||
|
virtual bigtime_t InitialLatency() const;
|
||||||
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
virtual status_t Read(void* buffer, int64 pos, int64 frames);
|
||||||
|
|
||||||
virtual status_t InitCheck() const;
|
virtual status_t InitCheck() const;
|
||||||
|
|||||||
@@ -115,7 +115,14 @@ MediaTrackAudioSupplier::Duration() const
|
|||||||
// #pragma mark - AudioReader
|
// #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
|
status_t
|
||||||
MediaTrackAudioSupplier::Read(void* buffer, int64 pos, int64 frames)
|
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
|
||||||
// Reads /frames/ frames from /position/ into /buffer/. The frames are not
|
read from the cache, but read frames are cached, if possible.
|
||||||
// read from the cache, but read frames are cached, if possible.
|
New cache buffers are stamped with the supplied time.
|
||||||
// New cache buffers are stamped with the supplied time.
|
If an error occurs, the untouched part of the buffer is set to 0.
|
||||||
// If an error occurs, the untouched part of the buffer is set to 0.
|
*/
|
||||||
status_t
|
status_t
|
||||||
MediaTrackAudioSupplier::_ReadUncachedFrames(void* buffer, int64 position,
|
MediaTrackAudioSupplier::_ReadUncachedFrames(void* buffer, int64 position,
|
||||||
int64 frames, bigtime_t time)
|
int64 frames, bigtime_t time)
|
||||||
{
|
{
|
||||||
TRACE("_ReadUncachedFrames()\n");
|
TRACE("_ReadUncachedFrames()\n");
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2000-2004 Ingo Weinhold <[email protected]>
|
* Copyright 2000-2004 Ingo Weinhold <[email protected]>
|
||||||
* Copyright © 2006-2008 Stephan Aßmus <[email protected]>
|
* Copyright 2006-2008 Stephan Aßmus <[email protected]>
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef MEDIA_TRACK_AUDIO_SUPPLIER_H
|
#ifndef MEDIA_TRACK_AUDIO_SUPPLIER_H
|
||||||
#define MEDIA_TRACK_AUDIO_SUPPLIER_H
|
#define MEDIA_TRACK_AUDIO_SUPPLIER_H
|
||||||
|
|
||||||
|
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
|
|
||||||
#include "AudioTrackSupplier.h"
|
#include "AudioTrackSupplier.h"
|
||||||
|
|
||||||
|
|
||||||
class BMediaTrack;
|
class BMediaTrack;
|
||||||
struct media_codec_info;
|
struct media_codec_info;
|
||||||
struct media_format;
|
struct media_format;
|
||||||
|
|
||||||
|
|
||||||
class MediaTrackAudioSupplier : public AudioTrackSupplier {
|
class MediaTrackAudioSupplier : public AudioTrackSupplier {
|
||||||
public:
|
public:
|
||||||
MediaTrackAudioSupplier(BMediaTrack* track,
|
MediaTrackAudioSupplier(BMediaTrack* track,
|
||||||
int32 trackIndex);
|
int32 trackIndex);
|
||||||
virtual ~MediaTrackAudioSupplier();
|
virtual ~MediaTrackAudioSupplier();
|
||||||
@@ -27,6 +30,7 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier {
|
|||||||
|
|
||||||
// AudioReader interface
|
// AudioReader interface
|
||||||
// (needed to reuse the class as AudioResampler input)
|
// (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 Read(void* buffer, int64 pos, int64 frames);
|
||||||
|
|
||||||
virtual status_t InitCheck() const;
|
virtual status_t InitCheck() const;
|
||||||
@@ -34,7 +38,7 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier {
|
|||||||
virtual int32 TrackIndex() const
|
virtual int32 TrackIndex() const
|
||||||
{ return fTrackIndex; }
|
{ return fTrackIndex; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Buffer;
|
struct Buffer;
|
||||||
void _InitFromTrack();
|
void _InitFromTrack();
|
||||||
|
|
||||||
|
|||||||
@@ -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 license.
|
* All Rights Reserved. Distributed under the terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "ProxyAudioSupplier.h"
|
#include "ProxyAudioSupplier.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -33,8 +35,9 @@ using std::swap;
|
|||||||
|
|
||||||
struct PlayingInterval {
|
struct PlayingInterval {
|
||||||
PlayingInterval(bigtime_t startTime, bigtime_t endTime)
|
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)
|
ProxyAudioSupplier::ProxyAudioSupplier(PlaybackManager* playbackManager)
|
||||||
: fSupplierLock("audio supplier lock")
|
:
|
||||||
|
fSupplierLock("audio supplier lock"),
|
||||||
|
|
||||||
, fPlaybackManager(playbackManager)
|
fPlaybackManager(playbackManager),
|
||||||
, fVideoFrameRate(25.0)
|
fVideoFrameRate(25.0),
|
||||||
, fVolume(1.0)
|
fVolume(1.0),
|
||||||
|
|
||||||
, fSupplier(NULL)
|
fSupplier(NULL),
|
||||||
, fAdapter(NULL)
|
fAdapter(NULL),
|
||||||
, fVolumeConverter(NULL)
|
fVolumeConverter(NULL),
|
||||||
, fAudioResampler()
|
fAudioResampler()
|
||||||
{
|
{
|
||||||
TRACE("ProxyAudioSupplier()\n");
|
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
|
status_t
|
||||||
ProxyAudioSupplier::GetFrames(void* buffer, int64 frameCount,
|
ProxyAudioSupplier::GetFrames(void* buffer, int64 frameCount,
|
||||||
bigtime_t startTime, bigtime_t endTime)
|
bigtime_t startTime, bigtime_t endTime)
|
||||||
@@ -100,7 +116,7 @@ ProxyAudioSupplier::GetFrames(void* buffer, int64 frameCount,
|
|||||||
ERROR("GetFrames() - zero duration audio interval! start "
|
ERROR("GetFrames() - zero duration audio interval! start "
|
||||||
"time: %lld\n", intervalStartTime);
|
"time: %lld\n", intervalStartTime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!playingIntervals.AddItem(interval)) {
|
if (!playingIntervals.AddItem(interval)) {
|
||||||
delete interval;
|
delete interval;
|
||||||
error = B_NO_MEMORY;
|
error = B_NO_MEMORY;
|
||||||
@@ -182,7 +198,7 @@ ProxyAudioSupplier::SetFormat(const media_format& format)
|
|||||||
{
|
{
|
||||||
//printf("ProxyAudioSupplier::SetFormat()\n");
|
//printf("ProxyAudioSupplier::SetFormat()\n");
|
||||||
#ifdef TRACE_PROXY_AUDIO_SUPPLIER
|
#ifdef TRACE_PROXY_AUDIO_SUPPLIER
|
||||||
char string[256];
|
char string[256];
|
||||||
string_for_format(format, string, 256);
|
string_for_format(format, string, 256);
|
||||||
TRACE("SetFormat(%s)\n", string);
|
TRACE("SetFormat(%s)\n", string);
|
||||||
#endif
|
#endif
|
||||||
@@ -258,6 +274,7 @@ ProxyAudioSupplier::Volume()
|
|||||||
|
|
||||||
// #pragma mark - audio/video/frame/time conversion
|
// #pragma mark - audio/video/frame/time conversion
|
||||||
|
|
||||||
|
|
||||||
int64
|
int64
|
||||||
ProxyAudioSupplier::_AudioFrameForVideoFrame(int64 frame) const
|
ProxyAudioSupplier::_AudioFrameForVideoFrame(int64 frame) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2008 Stephan Aßmus <[email protected]>
|
* Copyright 2008 Stephan Aßmus <[email protected]>
|
||||||
* All Rights Reserved. Distributed under the terms of the MIT license.
|
* All Rights Reserved. Distributed under the terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
#ifndef PROXY_AUDIO_SUPPLIER_H
|
#ifndef PROXY_AUDIO_SUPPLIER_H
|
||||||
#define PROXY_AUDIO_SUPPLIER_H
|
#define PROXY_AUDIO_SUPPLIER_H
|
||||||
|
|
||||||
|
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
|
|
||||||
#include "AudioResampler.h"
|
#include "AudioResampler.h"
|
||||||
@@ -26,6 +27,7 @@ public:
|
|||||||
virtual status_t GetFrames(void* buffer, int64 frameCount,
|
virtual status_t GetFrames(void* buffer, int64 frameCount,
|
||||||
bigtime_t startTime, bigtime_t endTime);
|
bigtime_t startTime, bigtime_t endTime);
|
||||||
|
|
||||||
|
virtual bigtime_t InitialLatency() const;
|
||||||
virtual void SetFormat(const media_format& format);
|
virtual void SetFormat(const media_format& format);
|
||||||
virtual const media_format& Format() const;
|
virtual const media_format& Format() const;
|
||||||
|
|
||||||
@@ -49,16 +51,16 @@ private:
|
|||||||
void* _SkipFrames(void* buffer, int64 frames) const;
|
void* _SkipFrames(void* buffer, int64 frames) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BLocker fSupplierLock;
|
mutable BLocker fSupplierLock;
|
||||||
|
|
||||||
PlaybackManager* fPlaybackManager;
|
PlaybackManager* fPlaybackManager;
|
||||||
float fVideoFrameRate;
|
float fVideoFrameRate;
|
||||||
float fVolume;
|
float fVolume;
|
||||||
|
|
||||||
AudioTrackSupplier* fSupplier;
|
AudioTrackSupplier* fSupplier;
|
||||||
AudioReader* fAdapter;
|
AudioReader* fAdapter;
|
||||||
AudioVolumeConverter* fVolumeConverter;
|
AudioVolumeConverter* fVolumeConverter;
|
||||||
AudioResampler fAudioResampler;
|
AudioResampler fAudioResampler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user