From 7ee2c8049caebce89fd72e544a5db9f94cc6613f Mon Sep 17 00:00:00 2001 From: beveloper Date: Sun, 15 Jun 2003 18:17:56 +0000 Subject: [PATCH] Internal API rewritten, BMediaNode and derived classes functionality implemented. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3525 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../media/media-add-ons/mixer/AudioMixer.cpp | 498 +++++++----------- .../media/media-add-ons/mixer/AudioMixer.h | 53 +- .../media-add-ons/mixer/FillMixBuffer.cpp | 403 -------------- .../media/media-add-ons/mixer/IOStructures.h | 43 -- src/add-ons/media/media-add-ons/mixer/Jamfile | 1 - .../media/media-add-ons/mixer/MixerCore.cpp | 97 +++- .../media/media-add-ons/mixer/MixerCore.h | 16 +- .../media/media-add-ons/mixer/MixerInput.cpp | 6 + .../media/media-add-ons/mixer/MixerInput.h | 1 + .../media/media-add-ons/mixer/MixerOutput.cpp | 6 +- .../media/media-add-ons/mixer/MixerOutput.h | 3 +- .../media/media-add-ons/mixer/license.txt | 31 -- .../media/media-add-ons/mixer/readme.txt | 37 -- 13 files changed, 311 insertions(+), 884 deletions(-) delete mode 100644 src/add-ons/media/media-add-ons/mixer/FillMixBuffer.cpp delete mode 100644 src/add-ons/media/media-add-ons/mixer/IOStructures.h delete mode 100644 src/add-ons/media/media-add-ons/mixer/license.txt delete mode 100644 src/add-ons/media/media-add-ons/mixer/readme.txt diff --git a/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp b/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp index c37b3e46f0..babe68bde1 100644 --- a/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp +++ b/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp @@ -1,10 +1,8 @@ -// AudioMixer.cpp -/* - - By David Shipman, 2002 - -*/ - +/* AudioMixer + * + * First implementation by David Shipman, 2002 + * Rewritten by Marcus Overhagen, 2003 + */ #include #include #include @@ -27,13 +25,11 @@ AudioMixer::AudioMixer(BMediaAddOn *addOn) BControllable(), BMediaEventLooper(), fAddOn(addOn), - fWeb(NULL), - fLatency(1), + fCore(new MixerCore), + fWeb(0), + fBufferGroup(0), + fDownstreamLatency(1), fInternalLatency(1), - fStartTime(0), - fFramesSent(0), - fOutputEnabled(true), - fBufferGroup(NULL), fDisableStop(false) { BMediaNode::AddNodeKind(B_SYSTEM_MIXER); @@ -52,13 +48,13 @@ AudioMixer::AudioMixer(BMediaAddOn *addOn) AudioMixer::~AudioMixer() { - BMediaEventLooper::Quit(); SetParameterWeb(NULL); - fWeb = NULL; - - // any other cleanup goes here + delete fCore; + delete fBufferGroup; + + DEBUG_ONLY(fCore = 0; fBufferGroup = 0; fWeb = 0); } void @@ -84,13 +80,8 @@ void AudioMixer::Stop(bigtime_t performance_time, bool immediate) BMediaAddOn * AudioMixer::AddOn(int32 *internal_id) const { - if(fAddOn) - { - *internal_id = 0; - return fAddOn; - } - else - return NULL; + *internal_id = 0; + return fAddOn; } // @@ -99,14 +90,14 @@ AudioMixer::AddOn(int32 *internal_id) const status_t AudioMixer::GetParameterValue(int32 id, bigtime_t *last_change, - void *value, size_t *ioSize) + void *value, size_t *ioSize) { return B_ERROR; } void AudioMixer::SetParameterValue(int32 id, bigtime_t when, - const void *value, size_t ioSize) + const void *value, size_t size) { } @@ -115,11 +106,10 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when, // status_t -AudioMixer::HandleMessage( int32 message, const void *data, size_t size) +AudioMixer::HandleMessage(int32 message, const void *data, size_t size) { // since we're using a mediaeventlooper, there shouldn't be any messages return B_ERROR; - } status_t @@ -281,8 +271,6 @@ AudioMixer::Connected(const media_source &producer, const media_destination &whe if (where.id != 0 || where.port != ControlPort()) return B_MEDIA_BAD_DESTINATION; - media_input input; - fCore->Lock(); // we assign a new id (!= 0) to the newly created input @@ -327,14 +315,23 @@ AudioMixer::Disconnected(const media_source &producer, const media_destination & } status_t -AudioMixer::FormatChanged( const media_source &producer, const media_destination &consumer, - int32 change_tag, const media_format &format) +AudioMixer::FormatChanged(const media_source &producer, const media_destination &consumer, + int32 change_tag, const media_format &format) { + // at some point in the future (indicated by change_tag and RequestCompleted()), + // we will receive buffers in a different format + + if (consumer.port != ControlPort() || consumer.id == 0) + return B_MEDIA_BAD_DESTINATION; + + // XXX we should not apply the format change at this point - // XXX tell core about format change - void InputFormatChanged(int32 inputID, const media_format *format); - printf("Format changed\n"); - return B_ERROR; + // tell core about format change + fCore->Lock(); + fCore->InputFormatChanged(consumer.id, &format); + fCore->Unlock(); + + return B_OK; } // @@ -375,11 +372,6 @@ AudioMixer::FormatProposal(const media_source &output, media_format *ioFormat) // we require a raw audio format if (ioFormat->type != B_MEDIA_RAW_AUDIO) return B_MEDIA_BAD_FORMAT; - - // XXX tell core about format change - void OutputFormatChanged(const media_format *format); - - } status_t @@ -387,7 +379,7 @@ AudioMixer::FormatChangeRequested(const media_source &source, const media_destin media_format *io_format, int32 *_deprecated_) { // the downstream consumer node (soundcard) requested that we produce - // another format, we need to check if the format is accecptable and + // another format, we need to check if the format is acceptable and // remove any wildcards before returning OK. fCore->Lock(); @@ -411,6 +403,13 @@ AudioMixer::FormatChangeRequested(const media_source &source, const media_destin /* remove wildcards */ io_format->SpecializeTo(&fDefaultFormat); + + // apply format change + fCore->Lock(); + fCore->OutputFormatChanged(io_format); + fCore->Unlock(); + + return B_OK; err: fCore->Unlock(); @@ -423,11 +422,8 @@ AudioMixer::GetNextOutput(int32 *cookie, media_output *out_output) if (*cookie != 0) return B_BAD_INDEX; - MixerOutput *output; - status_t rv; - fCore->Lock(); - output = fCore->Output(); + MixerOutput *output = fCore->Output(); if (output) { *out_output = output->MediaOutput(); } else { @@ -441,7 +437,7 @@ AudioMixer::GetNextOutput(int32 *cookie, media_output *out_output) fCore->Unlock(); *cookie += 1; - return B_OK + return B_OK; } status_t @@ -454,32 +450,21 @@ AudioMixer::DisposeOutputCookie(int32 cookie) status_t AudioMixer::SetBufferGroup(const media_source &for_source, BBufferGroup *newGroup) { - - if (! IsValidSource(for_source)) + // the downstream consumer (soundcard) node asks us to use another + // BBufferGroup (might be NULL). We only have one output (id 0) + if (for_source.port != ControlPort() || for_source.id != 0) return B_MEDIA_BAD_SOURCE; if (newGroup == fBufferGroup) // we're already using this buffergroup return B_OK; - - // Ahh, someone wants us to use a different buffer group. At this point we delete - // the one we are using and use the specified one instead. If the specified group is - // NULL, we need to recreate one ourselves, and use *that*. Note that if we're - // caching a BBuffer that we requested earlier, we have to Recycle() that buffer - // *before* deleting the buffer group, otherwise we'll deadlock waiting for that - // buffer to be recycled! - delete fBufferGroup; // waits for all buffers to recycle - if (newGroup != NULL) - { - // we were given a valid group; just use that one from now on - fBufferGroup = newGroup; - } - else - { - // we were passed a NULL group pointer; that means we construct - // our own buffer group to use from now on - AllocateBuffers(); - } - + + fCore->Lock(); + if (!newGroup) + newGroup = CreateBufferGroup(); + fCore->SetOutputBufferGroup(newGroup); + delete fBufferGroup; + fBufferGroup = newGroup; + fCore->Unlock(); return B_OK; } @@ -497,146 +482,109 @@ AudioMixer::GetLatency(bigtime_t *out_latency) status_t AudioMixer::PrepareToConnect(const media_source &what, const media_destination &where, - media_format *format, media_source *out_source, char *out_name) + media_format *format, media_source *out_source, char *out_name) { // PrepareToConnect() is the second stage of format negotiations that happens - // inside BMediaRoster::Connect(). At this point, the consumer's AcceptFormat() + // inside BMediaRoster::Connect(). At this point, the consumer's AcceptFormat() // method has been called, and that node has potentially changed the proposed - // format. It may also have left wildcards in the format. PrepareToConnect() + // format. It may also have left wildcards in the format. PrepareToConnect() // *must* fully specialize the format before returning! + // we also create the new output connection and return it in out_source. -/* - -he PrepareToConnect() hook is called before a new connection between the source whichSource and the destination whichDestination is established, in -order to give your producer one last chance to specialize any wildcards that remain in the format (although by this point there shouldn't be any, you should -check anyway). -Your implementation should, additionally, return in outSource the source to be used for the connection, and should fill the outName buffer with the name the -connection will be given; the consumer will see this in the outInput->name argument specified to BBufferConsumer::Connected(). If your node doesn't -care what the name is, you can leave the outName untouched. - -*/ - - // trying to connect something that isn't our source? - if (! IsValidSource(what)) + // is the source valid? + if (what.port != ControlPort() || what.id != 0) return B_MEDIA_BAD_SOURCE; + // is the format acceptable? + if (format->type != B_MEDIA_RAW_AUDIO && format->type != B_MEDIA_UNKNOWN_TYPE) + return B_MEDIA_BAD_FORMAT; + + fCore->Lock(); + // are we already connected? - if (fOutput.destination != media_destination::null) + if (fCore->Output() != 0) { + fCore->Unlock(); return B_MEDIA_ALREADY_CONNECTED; + } - // the format may not yet be fully specialized (the consumer might have - // passed back some wildcards). Finish specializing it now, and return an - // error if we don't support the requested format. - if (format->type != B_MEDIA_RAW_AUDIO) - return B_MEDIA_BAD_FORMAT; - - // CHANGE_THIS - we're messing around with formats, need to clean up - // still need to check u.raw_audio.format + /* set source and suggest a name */ + *out_source = what; + strcpy(out_name, "Mixer Output"); + + /* remove wildcards */ + format->SpecializeTo(&fDefaultFormat); + + /* add output to core */ + media_output output; + output.node = Node(); + output.source = *out_source; + output.destination = where; + output.format = *format; + strcpy(output.name, out_name); - if (format->u.raw_audio.format == media_raw_audio_format::wildcard.format) - format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; - - if ((format->u.raw_audio.format != media_raw_audio_format::B_AUDIO_FLOAT) && // currently support floating point - (format->u.raw_audio.format != media_raw_audio_format::B_AUDIO_SHORT)) // and 16bit int audio - return B_MEDIA_BAD_FORMAT; + fCore->EnableOutput(false); + fCore->AddOutput(output); - // all fields MUST be validated here - // or else the consumer is prone to divide-by-zero errors - - if(format->u.raw_audio.frame_rate == media_raw_audio_format::wildcard.frame_rate) - format->u.raw_audio.frame_rate = 44100; - - if(format->u.raw_audio.channel_count == media_raw_audio_format::wildcard.channel_count) - format->u.raw_audio.channel_count = 2; - - if(format->u.raw_audio.byte_order == media_raw_audio_format::wildcard.byte_order) - format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; - - if (format->u.raw_audio.buffer_size == media_raw_audio_format::wildcard.buffer_size) - format->u.raw_audio.buffer_size = 1024; // pick something comfortable to suggest - - - // Now reserve the connection, and return information about it - fOutput.destination = where; - fOutput.format = *format; - *out_source = fOutput.source; - strncpy(out_name, fOutput.name, B_MEDIA_NAME_LENGTH); // strncpy? + fCore->Unlock(); return B_OK; } void -AudioMixer::Connect( status_t error, const media_source &source, const media_destination &dest, - const media_format &format, char *io_name) +AudioMixer::Connect(status_t error, const media_source &source, const media_destination &dest, + const media_format &format, char *io_name) { printf("AudioMixer::Connect\n"); - // we need to check which output dest refers to - we only have one for now - - if (error) - { - fOutput.destination = media_destination::null; - fOutput.format = fPrefOutputFormat; + if (error != B_OK) { + // if an error occured, remove output from core + printf("AudioMixer::Connect failed, removing connction\n"); + fCore->Lock(); + fCore->RemoveOutput(); + fCore->Unlock(); return; } - - // connection is confirmed, record information and send output name - fOutput.destination = dest; - fOutput.format = format; - strncpy(io_name, fOutput.name, B_MEDIA_NAME_LENGTH); - + // if the connection has no name, we set it now + if (strlen(io_name) == 0) + strcpy(io_name, "Mixer Output"); + // Now that we're connected, we can determine our downstream latency. - // Do so, then make sure we get our events early enough. media_node_id id; - FindLatencyFor(fOutput.destination, &fLatency, &id); - printf("Downstream Latency is %Ld usecs\n", fLatency); + FindLatencyFor(dest, &fDownstreamLatency, &id); + printf("AudioMixer: Downstream Latency is %Ld usecs\n", fDownstreamLatency); - // we need at least the length of a full output buffer's latency (I think?) + // SetDuration of one buffer + SetBufferDuration((1000000 * (format.u.raw_audio.buffer_size / ((format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) * format.u.raw_audio.channel_count))) / format.u.raw_audio.frame_rate); - size_t sample_size = fOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK; + printf("AudioMixer: buffer duration is %Ld usecs\n", BufferDuration()); - size_t framesPerBuffer = (fOutput.format.u.raw_audio.buffer_size / sample_size) / fOutput.format.u.raw_audio.channel_count; + // Our internal latency is at least the length of a full output buffer + // XXX we use two for now + fInternalLatency = 2 * BufferDuration(); + printf("AudioMixer: Internal latency is %Ld usecs\n", fInternalLatency); - //fInternalLatency = (framesPerBuffer / fOutput.format.u.raw_audio.frame_rate); // test * 1000000 - - void *mouse = malloc(fOutput.format.u.raw_audio.buffer_size); - - bigtime_t latency_start = TimeSource()->RealTime(); - FillMixBuffer(mouse, fOutput.format.u.raw_audio.buffer_size); - bigtime_t latency_end = TimeSource()->RealTime(); - - fInternalLatency = latency_end - latency_start; - printf("Internal latency is %Ld usecs\n", fInternalLatency); - - // use a higher internal latency to be able to process buffers that arrive late - // XXX does this make sense? - if (fInternalLatency < 5000) - fInternalLatency = 5000; - - delete mouse; - - // might need to tweak the latency - SetEventLatency(fLatency + fInternalLatency); + SetEventLatency(fDownstreamLatency + fInternalLatency); printf("AudioMixer: SendLatencyChange %Ld\n", EventLatency()); SendLatencyChange(source, dest, EventLatency()); - // calculate buffer duration and set it - if (fOutput.format.u.raw_audio.frame_rate == 0) { - // XXX must be adjusted later when the format is known - SetBufferDuration((framesPerBuffer * 1000000LL) / 44100); - } else { - SetBufferDuration((framesPerBuffer * 1000000LL) / fOutput.format.u.raw_audio.frame_rate); - } - // Set up the buffer group for our connection, as long as nobody handed us a // buffer group (via SetBufferGroup()) prior to this. That can happen, for example, // if the consumer calls SetOutputBuffersFor() on us from within its Connected() // method. if (!fBufferGroup) - AllocateBuffers(); + fBufferGroup = CreateBufferGroup(); + + ASSERT(fCore->Output() != 0); + ASSERT(fCore->Output()->MediaOutput().format == format); + + fCore->Lock(); + fCore->EnableOutput(true); + fCore->SetTimeSource(TimeSource()->ID()); + fCore->SetOutputBufferGroup(fBufferGroup); + fCore->Unlock(); } @@ -645,15 +593,28 @@ AudioMixer::Disconnect(const media_source &what, const media_destination &where) { printf("AudioMixer::Disconnect\n"); - // Make sure that our connection is the one being disconnected - if ((where == fOutput.destination) && (what == fOutput.source)) // change later for multisource outputs - { - fOutput.destination = media_destination::null; - fOutput.format = fPrefOutputFormat; - delete fBufferGroup; - fBufferGroup = NULL; - } + + fCore->Lock(); + // Make sure that our connection is the one being disconnected + MixerOutput * output = fCore->Output(); + if (!output || output->MediaOutput().node != Node() || output->MediaOutput().source != what || output->MediaOutput().destination != where) { + FATAL("AudioMixer::Disconnect can't disconnect (wrong connection)\n"); + fCore->Unlock(); + return; + } + + // force a stop + fCore->Stop(); + + fCore->RemoveOutput(); + + // destroy buffer group + delete fBufferGroup; + fBufferGroup = 0; + fCore->SetOutputBufferGroup(0); + + fCore->Unlock(); } @@ -664,7 +625,8 @@ AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much, big // is the only runmode in which we can do anything about this printf("AudioMixer::LateNoticeReceived, %Ld too late at %Ld\n", how_much, performance_time); - + +/* if (what == fOutput.source) { if (RunMode() == B_INCREASE_LATENCY) { fInternalLatency += how_much; @@ -673,26 +635,26 @@ AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much, big fInternalLatency = 50000; printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency); - SetEventLatency(fLatency + fInternalLatency); + SetEventLatency(fDownstreamLatency + fInternalLatency); // printf("AudioMixer: SendLatencyChange %Ld (2)\n", EventLatency()); // SendLatencyChange(source, dest, EventLatency()); } } +*/ } void AudioMixer::EnableOutput(const media_source &what, bool enabled, int32 *_deprecated_) { - - // right now we've only got one output... check this against the supplied - // media_source and set its state accordingly... - - if (what == fOutput.source) - { - fOutputEnabled = enabled; - } + // we only have one output + if (what.id != 0 || what.port != ControlPort()) + return; + + fCore->Lock(); + fCore->EnableOutput(enabled); + fCore->Unlock(); } @@ -703,33 +665,19 @@ AudioMixer::EnableOutput(const media_source &what, bool enabled, int32 *_depreca void AudioMixer::NodeRegistered() { - Run(); - - fOutput.node = Node(); - - - for (int i = 0; i < 5; i++) - { - - media_input *newInput = new media_input; - - newInput->format = fPrefInputFormat; - newInput->source = media_source::null; - newInput->destination.port = ControlPort(); - newInput->destination.id = i; - newInput->node = Node(); - strcpy(newInput->name, "Free"); // - - mixer_input *mixerInput = new mixer_input(*newInput); - - fMixerInputs.AddItem(mixerInput); - - } - - SetPriority(120); + SetPriority(8); +// SetPriority(120); } +void +AudioMixer::SetTimeSource(BTimeSource * time_source) +{ + printf("AudioMixer::SetTimeSource: timesource is now %ld\n", time_source->ID()); + fCore->Lock(); + fCore->SetTimeSource(time_source->ID()); + fCore->Unlock(); +} void AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, bool realTimeEvent) @@ -744,142 +692,52 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo break; } - case SEND_NEW_BUFFER_EVENT: + case BTimedEventQueue::B_START: { - // if the output is connected and enabled, send a bufffer - if (fOutputEnabled && fOutput.destination != media_destination::null) - SendNewBuffer(event->event_time); - - // if this is the first buffer, mark with the start time - // we need this to calculate the other buffer times - if (fStartTime == 0) { - fStartTime = event->event_time; + if (RunState() != B_STARTED) { + fCore->Lock(); + fCore->Start(event->event_time); + fCore->Unlock(); } - - // count frames that have been played - size_t sample_size = fOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK; - int framesperbuffer = (fOutput.format.u.raw_audio.buffer_size / (sample_size * fOutput.format.u.raw_audio.channel_count)); - - fFramesSent += framesperbuffer; - - // calculate the start time for the next event and add the event - bigtime_t nextevent = bigtime_t(fStartTime + double(fFramesSent / fOutput.format.u.raw_audio.frame_rate) * 1000000.0); - media_timed_event nextBufferEvent(nextevent, SEND_NEW_BUFFER_EVENT); - EventQueue()->AddEvent(nextBufferEvent); break; } - - case BTimedEventQueue::B_START: - - if (RunState() != B_STARTED) - { - // We want to start sending buffers now, so we set up the buffer-sending bookkeeping - // and fire off the first "produce a buffer" event. - fStartTime = 0; - fFramesSent = 0; - - //fThread = spawn_thread(_mix_thread_, "audio mixer thread", B_REAL_TIME_PRIORITY, this); - - media_timed_event firstBufferEvent(event->event_time, SEND_NEW_BUFFER_EVENT); - - // Alternatively, we could call HandleEvent() directly with this event, to avoid a trip through - // the event queue, like this: - // - // this->HandleEvent(&firstBufferEvent, 0, false); - // - EventQueue()->AddEvent(firstBufferEvent); - - // fStartTime = event->event_time; - - } - - break; case BTimedEventQueue::B_STOP: { // stopped - don't process any more buffers, flush all buffers from eventqueue - EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER); - EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, SEND_NEW_BUFFER_EVENT); + fCore->Lock(); + fCore->Stop(); + fCore->Unlock(); break; } case BTimedEventQueue::B_DATA_STATUS: { - printf("DataStatus message\n"); - - mixer_input *mixerInput; - - int inputcount = fMixerInputs.CountItems(); - - for (int i = 0; i < inputcount; i++) - { - mixerInput = (mixer_input *)fMixerInputs.ItemAt(i); - if (mixerInput->fInput.destination == (media_destination &)event->pointer) - { - - printf("Valid DatasStatus destination\n"); - - mixerInput->fProducerDataStatus = event->data; - - if (mixerInput->fProducerDataStatus == B_DATA_AVAILABLE) - printf("B_DATA_AVAILABLE\n"); - else if (mixerInput->fProducerDataStatus == B_DATA_NOT_AVAILABLE) - printf("B_DATA_NOT_AVAILABLE\n"); - else if (mixerInput->fProducerDataStatus == B_PRODUCER_STOPPED) - printf("B_PRODUCER_STOPPED\n"); - - i = inputcount; - - } - } break; } default: - break; } - } // // AudioMixer methods // - -void -AudioMixer::AllocateBuffers() + +BBufferGroup * +AudioMixer::CreateBufferGroup() { - - // allocate enough buffers to span our downstream latency, plus one - size_t size = fOutput.format.u.raw_audio.buffer_size; - int32 count = int32((fLatency / (BufferDuration() + 1)) + 1); + // allocate enough buffers to span our downstream latency (plus one for rounding up), plus one extra + int32 count = int32(fDownstreamLatency / BufferDuration()) + 2; - if (count < 3) { - printf("AudioMixer: calculated only %ld buffers, that's not enough\n", count); - count = 3; - } - - printf("AudioMixer: allocating %ld buffers\n", count); - fBufferGroup = new BBufferGroup(size, count); -} - -// use this later for separate threads - -int32 -AudioMixer::_mix_thread_(void *data) -{ - return ((AudioMixer *)data)->MixThread(); -} - -int32 -AudioMixer::MixThread() -{ - while (1) - { - snooze(500000); - } + fCore->Lock(); + uint32 size = fCore->OutputBufferSize(); + fCore->Unlock(); + printf("AudioMixer: allocating %ld buffers of %ld bytes each\n", count, size); + return new BBufferGroup(size, count); } diff --git a/src/add-ons/media/media-add-ons/mixer/AudioMixer.h b/src/add-ons/media/media-add-ons/mixer/AudioMixer.h index 3d62fc6e4e..c6609c5b3f 100644 --- a/src/add-ons/media/media-add-ons/mixer/AudioMixer.h +++ b/src/add-ons/media/media-add-ons/mixer/AudioMixer.h @@ -46,19 +46,19 @@ class AudioMixer : BParameterWeb * BuildParameterWeb(); // used to create the initial 'master' web void MakeWebForInput(char *name, media_format format); - void AllocateBuffers(); - status_t FillMixBuffer(void *outbuffer, size_t size); - - void SendNewBuffer(bigtime_t event_time); void HandleInputBuffer(BBuffer *buffer, bigtime_t lateness); + + BBufferGroup * CreateBufferGroup(); // BMediaNode methods BMediaAddOn * AddOn(int32*) const; // void SetRunMode(run_mode); // void Preroll(); - // void SetTimeSource(BTimeSource* time_source); - // status_t RequestCompleted(const media_request_info & info); + // status_t RequestCompleted(const media_request_info & info); + void NodeRegistered(); + void Stop(bigtime_t performance_time, bool immediate); + void SetTimeSource(BTimeSource * time_source); protected: @@ -176,43 +176,20 @@ class AudioMixer : // BMediaEventLooper methods - virtual void NodeRegistered(); - - virtual void Stop(bigtime_t performance_time, - bool immediate); - void HandleEvent( const media_timed_event *event, bigtime_t lateness, bool realTimeEvent = false); - // handle mixing in separate thread - // not implemented (yet) - - static int32 _mix_thread_(void *data); - int32 MixThread(); - + private: - - - - BMediaAddOn * fAddOn; - BParameterWeb * fWeb; // local pointer to parameterweb - - bigtime_t fLatency, fInternalLatency; // latency (downstream and internal) - bigtime_t fStartTime; // time node started - uint64 fFramesSent; // audio frames sent - bool fOutputEnabled; - - BBufferGroup * fBufferGroup; - - BList fMixerInputs; - - - bool fDisableStop; - - MixerCore *fCore; - media_format fDefaultFormat; - + BMediaAddOn *fAddOn; + MixerCore *fCore; + BParameterWeb *fWeb; // local pointer to parameterweb + BBufferGroup *fBufferGroup; + bigtime_t fDownstreamLatency; + bigtime_t fInternalLatency; + bool fDisableStop; + media_format fDefaultFormat; }; #endif diff --git a/src/add-ons/media/media-add-ons/mixer/FillMixBuffer.cpp b/src/add-ons/media/media-add-ons/mixer/FillMixBuffer.cpp deleted file mode 100644 index 2b61b6b993..0000000000 --- a/src/add-ons/media/media-add-ons/mixer/FillMixBuffer.cpp +++ /dev/null @@ -1,403 +0,0 @@ -#include "AudioMixer.h" -#include "IOStructures.h" - -#include -#include -#include -#include -#include -#include -#include - -status_t -AudioMixer::FillMixBuffer(void *outbuffer, size_t ioSize) -{ - - int32 outChannels = fOutput.format.u.raw_audio.channel_count; - - // we have an output buffer - now it needs to be filled! - - switch (fOutput.format.u.raw_audio.format) - { - case media_raw_audio_format::B_AUDIO_FLOAT: - { - float *outdata = (float*)outbuffer; - memset(outdata, 0, ioSize); // CHANGE_THIS - - int sampleCount = int(fOutput.format.u.raw_audio.buffer_size / sizeof(float)); - - for (int s = 0; s < sampleCount; s++) - { - outdata[s] = 0.0; // CHANGE_THIS - } - - int mixerInputCount = fMixerInputs.CountItems(); - - for (int c = 0; c < mixerInputCount; c++) - { - mixer_input *channel = (mixer_input *)fMixerInputs.ItemAt(c); - - if (channel->enabled == true) // still broken... FIX_THIS - { - int32 inChannels = channel->fInput.format.u.raw_audio.channel_count; - bool split = outChannels > inChannels; - bool mix = outChannels < inChannels; - - if (fOutput.format.u.raw_audio.frame_rate == channel->fInput.format.u.raw_audio.frame_rate) - { - switch (channel->fInput.format.u.raw_audio.format) - { - case media_raw_audio_format::B_AUDIO_FLOAT: - { - float *indata = (float *)channel->fData; - - if (split) { - printf("#### FillMixBuffer(): 1.Should split from B_AUDIO_FLOAT!\n"); - } else if (mix) { - printf("#### FillMixBuffer(): 1.Should mix from B_AUDIO_FLOAT!\n"); - } else { - int baseOffset = channel->fEventOffset / 4; - int maxOffset = int(channel->fDataSize / 4); - - int offsetWrap = maxOffset - baseOffset; - - int inputSample = baseOffset; - - for (int s = 0; s < sampleCount; s++) - { - outdata[s] = indata[inputSample]; - indata[inputSample] = 0; - - if (s == offsetWrap) - inputSample = 0; - else - inputSample ++; - } - - channel->fEventOffset = (channel->fEventOffset + fOutput.format.u.raw_audio.buffer_size) % - channel->fDataSize; - } - break; - } - - case media_raw_audio_format::B_AUDIO_SHORT: - { - int16 *indata = (int16 *)channel->fData; - - if (split) { - printf("#### FillMixBuffer(): 2.Should split from B_AUDIO_SHORT!\n"); - } else if (mix) { - printf("#### FillMixBuffer(): 2.Should mix from B_AUDIO_SHORT!\n"); - } else { - int baseOffset = channel->fEventOffset / 2; - int maxOffset = int(channel->fDataSize / 2); - - int offsetWrap = maxOffset - baseOffset; - - int inputSample = baseOffset; - - for (int s = 0; s < sampleCount; s++) - { - outdata[s] = outdata[s] + (indata[inputSample] / 32768.0); - // CHANGE_THIS indata[inputSample] = 0; - - if (s == offsetWrap) - inputSample = 0; - else - inputSample ++; - } - - channel->fEventOffset = (channel->fEventOffset + fOutput.format.u.raw_audio.buffer_size / 2) % - channel->fDataSize; - } - break; - } - } // input format - } else - printf("#### sample rate does not match - don't do anything\n"); - } // data available - } // channel loop - - /* - // The buffer is done - we still need to scale for the MainVolume... - // then check to see if anything is clipping, adjust if needed - */ - - for (int frameStart = 0; frameStart < sampleCount; frameStart += outChannels) - { - for (int channel = 0; channel < outChannels; channel ++) - { - int sample = frameStart + channel; - outdata[sample] = outdata[sample] * fMasterGainScale[channel]; - - //if (outdata[sample] > 1.0) - // outdata[sample] = 1.0; - // else if (outdata[sample] < -1.0) - // outdata[sample] = -1.0; - } - } - break; - } // cur-case - - case media_raw_audio_format::B_AUDIO_SHORT: - { - int16 *outdata = (int16*)outbuffer; - int sampleCount = int(fOutput.format.u.raw_audio.buffer_size / sizeof(int16)); - - int *clipoffset = new int[sampleCount]; - // keep a running tally of +/- clipping so we don't get rollaround distortion - // we only need this for int/char audio types - not float - - memset(outdata, 0, ioSize); - memset(clipoffset, 0, sizeof(int) * sampleCount); - - // for (int s = 0; s < sampleCount; s++) - // { - // clipoffset[s] = 0; - // } - - int mixerInputs = fMixerInputs.CountItems(); - if (mixerInputs == 0) - printf("#### mixer null\n"); - for (int c = 0; c < mixerInputs; c++) - { - mixer_input *channel = (mixer_input *)fMixerInputs.ItemAt(c); - - if (channel->enabled == true) // only use if there are buffers waiting (seems to be broken atm...) - { - // if (channel->fProducerDataStatus == B_DATA_AVAILABLE) - // printf("B_DATA_AVAILABLE\n"); - // else if (channel->fProducerDataStatus == B_DATA_NOT_AVAILABLE) - // printf("B_DATA_NOT_AVAILABLE\n"); - // else if (channel->fProducerDataStatus == B_PRODUCER_STOPPED) - // printf("B_PRODUCER_STOPPED\n"); - - int32 inChannels = channel->fInput.format.u.raw_audio.channel_count; - bool split = outChannels > inChannels; - bool mix = outChannels < inChannels; - - if (fOutput.format.u.raw_audio.frame_rate == channel->fInput.format.u.raw_audio.frame_rate) - { - switch (channel->fInput.format.u.raw_audio.format) - { - case media_raw_audio_format::B_AUDIO_FLOAT: - { - float *indata = (float *)channel->fData; - - if (split) { - int baseOffset = channel->fEventOffset / 4; - int maxOffset = int(channel->fDataSize / 4); - - int offsetWrap = maxOffset - baseOffset; - - int inputSample = baseOffset; - - for (int s = 0; s < sampleCount; s += 2) - { - if ((outdata[s] + int16(32767 * indata[inputSample])) > 32767) - clipoffset[s] = clipoffset[s] + 1; - else if ((outdata[s] + int16(32767 * indata[inputSample])) < -32768) - clipoffset[s] = clipoffset[s] - 1; - - if ((outdata[s + 1] + int16(32767 * indata[inputSample])) > 32767) - clipoffset[s + 1] = clipoffset[s + 1] + 1; - else if ((outdata[s] + int16(32767 * indata[inputSample])) < -32768) - clipoffset[s + 1] = clipoffset[s + 1] - 1; - - outdata[s] = outdata[s] + int16(32767 * indata[inputSample]); // CHANGE_THIS mixing - outdata[s + 1] = outdata[s]; - - indata[inputSample] = 0; - - if (s == offsetWrap) - inputSample = 0; - else - inputSample ++; - } - } else if (mix) { - printf("#### FillMixBuffer(): 3.Should mix from B_AUDIO_FLOAT!\n"); - } else { - int baseOffset = channel->fEventOffset / 4; - int maxOffset = int(channel->fDataSize / 4); - - int offsetWrap = maxOffset - baseOffset; - - int inputSample = baseOffset; - - for (int frameStart = 0; frameStart < sampleCount; frameStart += outChannels) - { - for (int chan = 0; chan < outChannels; chan ++) - { - int sample = frameStart + chan; - - int inputValue = int((32767 * indata[inputSample] * channel->fGainScale[chan]) + outdata[sample]); - - if (inputValue > 32767) - clipoffset[sample] = clipoffset[sample] + 1; - else if (inputValue < -32768) - clipoffset[sample] = clipoffset[sample] - 1; - - outdata[sample] = inputValue; // CHANGE_THIS - indata[inputSample] = 0; - - if (sample == offsetWrap) - inputSample = 0; - else - inputSample ++; - } - } - - channel->fEventOffset += (fOutput.format.u.raw_audio.buffer_size * 2); - if (channel->fEventOffset >= channel->fDataSize) - channel->fEventOffset -= channel->fDataSize; - } - break; - } - - case media_raw_audio_format::B_AUDIO_SHORT: - { - int16 *indata = (int16 *)channel->fData; - - if (split) { - printf("#### FillMixBuffer(): 4.Should split from B_AUDIO_SHORT!\n"); - } else if (mix) { - printf("#### FillMixBuffer(): 4.Should mix from B_AUDIO_SHORT!\n"); - } else { - // printf("#### FillMixBuffer(): 4.Should copy from B_AUDIO_SHORT!\n"); - int baseOffset = channel->fEventOffset / 2; - int maxOffset = int(channel->fDataSize / 2); - - int offsetWrap = maxOffset - baseOffset; - - int inputSample = baseOffset; - - for (int frameStart = 0; frameStart < sampleCount; frameStart += outChannels) - { - for (int chan = 0; chan < outChannels; chan ++) - { - int sample = frameStart + chan; - - int clipTest = int(outdata[sample] + (indata[inputSample] * channel->fGainScale[chan])); - - if (clipTest > 32767) - clipoffset[sample] = clipoffset[sample] + 1; - else if (clipTest < -32768) - clipoffset[sample] = clipoffset[sample] - 1; - - outdata[sample] = int16(outdata[sample] + (indata[inputSample] * channel->fGainScale[chan])); - indata[inputSample] = 0; - - if (sample == offsetWrap) - inputSample = 0; - else - inputSample ++; - - } - } - - channel->fEventOffset = (channel->fEventOffset + fOutput.format.u.raw_audio.buffer_size); - if (channel->fEventOffset >= channel->fDataSize) - channel->fEventOffset -= channel->fDataSize; - } - break; - } - - case media_raw_audio_format::B_AUDIO_INT: - { - int32 *indata = (int32 *)channel->fData; - - if (split) { - int baseOffset = channel->fEventOffset / 4; - int maxOffset = int(channel->fDataSize / 4); - - int offsetWrap = maxOffset - baseOffset; - - int inputSample = baseOffset; - - for (int s = 0; s < sampleCount; s += 2) { - if ((outdata[s] + (indata[inputSample] / 65536)) > 32767) - clipoffset[s] = clipoffset[s] + 1; - else if ((outdata[s] + (indata[inputSample] / 65536)) < -32768) - clipoffset[s] = clipoffset[s] - 1; - - if ((outdata[s + 1] + (indata[inputSample] / 65536)) > 32767) - clipoffset[s + 1] = clipoffset[s + 1] + 1; - else if ((outdata[s + 1] + (indata[inputSample] / 65536)) < -32768) - clipoffset[s + 1] = clipoffset[s + 1] - 1; - - outdata[s] = int16(outdata[s] + (indata[inputSample] / 65535)); // CHANGE_THIS mixing - outdata[s + 1] = outdata[s]; - - indata[inputSample] = 0; - - if (s == offsetWrap) - inputSample = 0; - else - inputSample ++; - } - } else if (mix) { - printf("#### FillMixBuffer(): 5.Should mix from B_AUDIO_INT!\n"); - } else { - int baseOffset = channel->fEventOffset / 4; - int maxOffset = int(channel->fDataSize / 4); - - int offsetWrap = maxOffset - baseOffset; - - int inputSample = baseOffset; - - for (int s = 0; s < sampleCount; s++) { - if ((outdata[s] + (indata[inputSample] / 65536)) > 32767) - clipoffset[s] = clipoffset[s] + 1; - else if ((outdata[s] + (indata[inputSample] / 65536)) < -32768) - clipoffset[s] = clipoffset[s] - 1; - - outdata[s] = int16(outdata[s] + (indata[inputSample] / 65536)); // CHANGE_THIS mixing - indata[inputSample] = 0; - - if (s == offsetWrap) - inputSample = 0; - else - inputSample ++; - } - } - - channel->fEventOffset = (channel->fEventOffset + (fOutput.format.u.raw_audio.buffer_size * 2)) - % channel->fDataSize; - break; - } - } - } else - printf("#### sample rate does not match - don't do anything\n"); - } - } - - // use our clipoffset to determine correct limits - - for (int frameStart = 0; frameStart < sampleCount; frameStart += outChannels) - { - for (int channel = 0; channel < outChannels; channel ++) - { - int sample = frameStart + channel; - - int scaledSample = int((outdata[sample] + (65536 * clipoffset[sample])) * fMasterGainScale[channel]); - - if (scaledSample < -32768) - outdata[sample] = -32768; - else if (scaledSample > 32767) - outdata[sample] = 32767; - else - outdata[sample] = scaledSample; //(int16) - } - } - - delete clipoffset; - break; - } - - default: - printf("##### oh no, unknown conversion %ld #####\n", fOutput.format.u.raw_audio.format); - } - - return B_OK; - -} diff --git a/src/add-ons/media/media-add-ons/mixer/IOStructures.h b/src/add-ons/media/media-add-ons/mixer/IOStructures.h deleted file mode 100644 index 627bb00f0d..0000000000 --- a/src/add-ons/media/media-add-ons/mixer/IOStructures.h +++ /dev/null @@ -1,43 +0,0 @@ -// IOStructures.h -/* - - Structures to represent IO channels in the AudioMixer node - By David Shipman, 2002 - -*/ - -#ifndef _IO_STRUCT_H -#define _IO_STRUCT_H - -class mixer_input -{ - - public: - - mixer_input(media_input &input); - ~mixer_input(); - - media_input fInput; - int32 fProducerDataStatus; // status of upstream data - bool enabled; // there is a buffer ready for mixing - char * fData; - - float * fGainScale; // multiplier for gain - computed at paramchange - float * fGainDisplay; // the value that will be displayed for gain - bigtime_t fGainDisplayLastChange; - - - int fMuteValue; // the value of the 'mute' control - bigtime_t fMuteValueLastChange; - - float fPanValue; // value of 'pan' control (only if mono) - bigtime_t fPanValueLastChange; - - - size_t fEventOffset; // offset (in bytes) of the start of the next - // _output_ buffer - use this for keeping in sync - size_t fDataSize; // size of ringbuffer - -}; - -#endif diff --git a/src/add-ons/media/media-add-ons/mixer/Jamfile b/src/add-ons/media/media-add-ons/mixer/Jamfile index 05d432aa99..72d4e50194 100644 --- a/src/add-ons/media/media-add-ons/mixer/Jamfile +++ b/src/add-ons/media/media-add-ons/mixer/Jamfile @@ -4,7 +4,6 @@ UsePrivateHeaders media ; Addon mixer.media_addon : media : AudioMixer.cpp - FillMixBuffer.cpp MixerAddOn.cpp MixerCore.cpp MixerInput.cpp diff --git a/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp b/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp index c0ab8fcf44..16f15fba70 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp @@ -33,32 +33,94 @@ MixerCore::AddOutput(const media_output &output) } bool -MixerCore::RemoveInput(const media_input &input) +MixerCore::RemoveInput(int32 inputID) { return true; } bool -MixerCore::RemoveOutput(const media_output &output) +MixerCore::RemoveOutput() { return true; } -void -MixerCore::OutputBufferLengthChanged(bigtime_t length) +int32 +MixerCore::CreateInputID() { - Lock(); - - Unlock(); + return 1; } - MixerInput * MixerCore::Input(int i) { return (MixerInput *)fInputs->ItemAt(i); } +MixerOutput * +MixerCore::Output() +{ + return fOutput; +} + +void +MixerCore::BufferReceived(BBuffer *buffer, bigtime_t lateness) +{ +} + +void +MixerCore::InputFormatChanged(int32 inputID, const media_format *format) +{ +} + +void +MixerCore::OutputFormatChanged(const media_format *format) +{ +} + +void +MixerCore::SetOutputBufferGroup(BBufferGroup *group) +{ +} + +void +MixerCore::SetTimeSource(media_node_id id) +{ +} + +void +MixerCore::EnableOutput(bool enabled) +{ +} + +void +MixerCore::Start(bigtime_t time) +{ +} + +void +MixerCore::Stop() +{ +} + +uint32 +MixerCore::OutputBufferSize() +{ + return 1; +} + +bool +MixerCore::IsStarted() +{ + return false; +} + +void +MixerCore::OutputBufferLengthChanged(bigtime_t length) +{ +} + + + /* void BufferReceived(BBuffer *buffer, bigtime_t lateness); @@ -79,4 +141,23 @@ MixerCore::Input(int i) break; } + +// use this later for separate threads + +int32 +AudioMixer::_mix_thread_(void *data) +{ + return ((AudioMixer *)data)->MixThread(); +} + +int32 +AudioMixer::MixThread() +{ + while (1) + { + snooze(500000); + } + +} + */ \ No newline at end of file diff --git a/src/add-ons/media/media-add-ons/mixer/MixerCore.h b/src/add-ons/media/media-add-ons/mixer/MixerCore.h index cba0aaa0c0..b7b486c832 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerCore.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerCore.h @@ -23,7 +23,7 @@ public: MixerInput *Input(int index); // index = 0 to count-1, NOT inputID MixerOutput *Output(); - + void Lock(); void Unlock(); @@ -32,8 +32,22 @@ public: void InputFormatChanged(int32 inputID, const media_format *format); void OutputFormatChanged(const media_format *format); + void SetOutputBufferGroup(BBufferGroup *group); + void SetTimeSource(media_node_id id); + void EnableOutput(bool enabled); + void Start(bigtime_t time); + void Stop(); + + uint32 OutputBufferSize(); + bool IsStarted(); + private: void OutputBufferLengthChanged(bigtime_t length); + // handle mixing in separate thread + // not implemented (yet) + + static int32 _mix_thread_(void *data); + int32 MixThread(); private: diff --git a/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp b/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp index 4dd176a48d..e1fcae8f0a 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp @@ -16,3 +16,9 @@ void MixerInput::BufferReceived(BBuffer *buffer) { } + +media_input & +MixerInput::MediaInput() +{ + return fInput; +} diff --git a/src/add-ons/media/media-add-ons/mixer/MixerInput.h b/src/add-ons/media/media-add-ons/mixer/MixerInput.h index 4852e5eee0..ae0daee336 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.h @@ -15,6 +15,7 @@ public: private: MixerCore *fCore; + media_input fInput; }; #endif diff --git a/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp b/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp index d6aaac795e..86120876ba 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp @@ -12,4 +12,8 @@ MixerOutput::~MixerOutput() { } -media_output MediaOutput(); +media_output & +MixerOutput::MediaOutput() +{ + return fOutput; +} diff --git a/src/add-ons/media/media-add-ons/mixer/MixerOutput.h b/src/add-ons/media/media-add-ons/mixer/MixerOutput.h index 10f1e5d609..ef4445b911 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerOutput.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerOutput.h @@ -9,10 +9,11 @@ public: MixerOutput(MixerCore *core); ~MixerOutput(); - media_output MediaOutput(); + media_output & MediaOutput(); private: MixerCore *fCore; + media_output fOutput; }; #endif diff --git a/src/add-ons/media/media-add-ons/mixer/license.txt b/src/add-ons/media/media-add-ons/mixer/license.txt deleted file mode 100644 index 86a4268fa9..0000000000 --- a/src/add-ons/media/media-add-ons/mixer/license.txt +++ /dev/null @@ -1,31 +0,0 @@ ----------------------- -Be Sample Code License ----------------------- - -Copyright 1991-1999, Be Incorporated. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions, and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions, and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/add-ons/media/media-add-ons/mixer/readme.txt b/src/add-ons/media/media-add-ons/mixer/readme.txt deleted file mode 100644 index 1981cf525c..0000000000 --- a/src/add-ons/media/media-add-ons/mixer/readme.txt +++ /dev/null @@ -1,37 +0,0 @@ -OpenBeOS Audio Mixer -David Shipman, 14/08/2002 - -Overview - -The node is based on a mediaeventlooper, using the HandleEvent loop to compile the mixed buffer output. -Each input creates a ringbuffer (fixed size "looped" buffer) for its input - this way buffer contents can be -placed in the ringbuffer and the buffer recycled immediately. - -Inputs are maintained using a list of mixer_input objects - inputs are created/destroyed dynamically when -producers connect/disconnect. - -Done - -- node functions as a replacement for the BeOS R5 mixer.media-addon -- IO/conversion between the major audio types (FLOAT, SHORT) -- interface mostly done (all gain controls operational) -- mixing with different gain levels is functional - -Tested - -- Output to emu10k1 (SBLive) -- Input from CL-Amp, file-readers, SoundPlay, music software - almost all work well - -To Do (vaguely in order of importance) - -- fix bugs -- format negotation fine-tuning - some nodes still connect with weird formats -- rewrite of buffer mixing routines - at the moment its really inefficient, and a total mess -- complete interface (add mutes, panning) -- multithreading (separate mix thread) -- mixer save (to save parameter states when a node is disconnected) - -Notes : - -Parts of this program are based on code under the Be Sample Code License. -This is included in the archive, in accordance with the license. \ No newline at end of file