12e9d6607Sbeveloper #include <Buffer.h> 27b0daf5cSbeveloper #include <string.h> 38d28117fSbeveloper #include <TimeSource.h> // XXX debug only 4678c2017Sbeveloper #include "MixerInput.h" 5678c2017Sbeveloper #include "MixerCore.h" 6e6c7c99fSbeveloper #include "MixerUtils.h" 77b0daf5cSbeveloper #include "Resampler.h" 888777023Sbeveloper #include "ByteSwap.h" 9e6c7c99fSbeveloper #include "debug.h" 10678c2017Sbeveloper 118d28117fSbeveloper MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrameRate, int32 mixFrameCount) 12e6c7c99fSbeveloper : fCore(core), 132e9d6607Sbeveloper fInput(input), 1488777023Sbeveloper fInputByteSwap(0), 151c237c18Sbeveloper fEnabled(true), 162e9d6607Sbeveloper fInputChannelInfo(0), 172e9d6607Sbeveloper fInputChannelCount(0), 182e9d6607Sbeveloper fInputChannelMask(0), 192e9d6607Sbeveloper fMixerChannelInfo(0), 202e9d6607Sbeveloper fMixerChannelCount(0), 212e9d6607Sbeveloper fMixBuffer(0), 227b0daf5cSbeveloper fMixBufferFrameRate(0), 237b0daf5cSbeveloper fMixBufferFrameCount(0), 24*e92593f4Sbeveloper fLastDataFrameWritten(-1), 25af8d0a4dSbeveloper fLastDataAvailableTime(-1), 26*e92593f4Sbeveloper fFractionalFrames(0.0), 277b0daf5cSbeveloper fResampler(0), 28356855c3Sbeveloper fRtmPool(0), 299c3be6a5Sbeveloper fUserOverridesChannelDestinations(false) 30678c2017Sbeveloper { 31e6c7c99fSbeveloper fix_multiaudio_format(&fInput.format.u.raw_audio); 32e6c7c99fSbeveloper PRINT_INPUT("MixerInput::MixerInput", fInput); 33e6c7c99fSbeveloper PRINT_CHANNEL_MASK(fInput.format); 342e9d6607Sbeveloper 352e9d6607Sbeveloper ASSERT(fInput.format.u.raw_audio.channel_count > 0); 362e9d6607Sbeveloper 379c3be6a5Sbeveloper for (int i = 0; i < MAX_CHANNEL_TYPES; i++) 389c3be6a5Sbeveloper fChannelTypeGain[i] = 1.0f; 399c3be6a5Sbeveloper 402e9d6607Sbeveloper fInputChannelCount = fInput.format.u.raw_audio.channel_count; 412e9d6607Sbeveloper fInputChannelMask = fInput.format.u.raw_audio.channel_mask; 422e9d6607Sbeveloper fInputChannelInfo = new input_chan_info[fInputChannelCount]; 432e9d6607Sbeveloper 4488777023Sbeveloper // perhaps we need byte swapping 4588777023Sbeveloper if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) { 4688777023Sbeveloper if ( fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT 4788777023Sbeveloper || fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT 4888777023Sbeveloper || fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) { 4988777023Sbeveloper fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format); 5088777023Sbeveloper } 5188777023Sbeveloper } 5288777023Sbeveloper 532e9d6607Sbeveloper // initialize fInputChannelInfo 542e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) { 552e9d6607Sbeveloper fInputChannelInfo[i].buffer_base = 0; // will be set by SetMixBufferFormat() 569c3be6a5Sbeveloper fInputChannelInfo[i].destination_mask = 0; // will be set by UpdateInputChannelDestinationMask() 572e9d6607Sbeveloper fInputChannelInfo[i].gain = 1.0; 582e9d6607Sbeveloper } 592e9d6607Sbeveloper 607b0daf5cSbeveloper // create resamplers 617b0daf5cSbeveloper fResampler = new Resampler * [fInputChannelCount]; 627b0daf5cSbeveloper for (int i = 0; i < fInputChannelCount; i++) 637b0daf5cSbeveloper fResampler[i] = new Resampler(fInput.format.u.raw_audio.format, media_raw_audio_format::B_AUDIO_FLOAT); 647b0daf5cSbeveloper 659c3be6a5Sbeveloper // fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateInputChannelDestinations() 662e9d6607Sbeveloper 678d28117fSbeveloper SetMixBufferFormat(mixFrameRate, mixFrameCount); 68678c2017Sbeveloper } 69678c2017Sbeveloper 70678c2017Sbeveloper MixerInput::~MixerInput() 71678c2017Sbeveloper { 722e9d6607Sbeveloper if (fMixBuffer) 732e9d6607Sbeveloper rtm_free(fMixBuffer); 74356855c3Sbeveloper if (fRtmPool) 75356855c3Sbeveloper rtm_delete_pool(fRtmPool); 762e9d6607Sbeveloper delete [] fInputChannelInfo; 772e9d6607Sbeveloper delete [] fMixerChannelInfo; 787b0daf5cSbeveloper 797b0daf5cSbeveloper // delete resamplers 807b0daf5cSbeveloper for (int i = 0; i < fInputChannelCount; i++) 817b0daf5cSbeveloper delete fResampler[i]; 827b0daf5cSbeveloper delete [] fResampler; 83678c2017Sbeveloper } 84678c2017Sbeveloper 85678c2017Sbeveloper void 86678c2017Sbeveloper MixerInput::BufferReceived(BBuffer *buffer) 87678c2017Sbeveloper { 8888777023Sbeveloper void *data; 8988777023Sbeveloper size_t size; 9088777023Sbeveloper bigtime_t start; 91*e92593f4Sbeveloper bigtime_t buffer_duration; 9288777023Sbeveloper 93d5848e21Sbeveloper if (!fMixBuffer) { 94a2ca4723Sbeveloper ERROR("MixerInput::BufferReceived: dropped incoming buffer as we don't have a mix buffer\n"); 95d5848e21Sbeveloper return; 96d5848e21Sbeveloper } 972e9d6607Sbeveloper 9888777023Sbeveloper data = buffer->Data(); 9988777023Sbeveloper size = buffer->SizeUsed(); 10088777023Sbeveloper start = buffer->Header()->start_time; 101*e92593f4Sbeveloper buffer_duration = duration_for_frames(fInput.format.u.raw_audio.frame_rate, size / bytes_per_frame(fInput.format.u.raw_audio)); 1028d28117fSbeveloper if (start < 0) { 103a2ca4723Sbeveloper ERROR("MixerInput::BufferReceived: buffer with negative start time of %Ld dropped\n", start); 1048d28117fSbeveloper return; 1058d28117fSbeveloper } 10688777023Sbeveloper 10788777023Sbeveloper // swap the byte order of this buffer, if necessary 10888777023Sbeveloper if (fInputByteSwap) 10988777023Sbeveloper fInputByteSwap->Swap(data, size); 11088777023Sbeveloper 111d91580cdSbeveloper int offset = frames_for_duration(fMixBufferFrameRate, start) % fMixBufferFrameCount; 1128d28117fSbeveloper 113191033efSbeveloper PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n", start, offset); 1147b0daf5cSbeveloper 115191033efSbeveloper int in_frames = size / bytes_per_frame(fInput.format.u.raw_audio); 116*e92593f4Sbeveloper double frames = double(in_frames * fMixBufferFrameRate) / fInput.format.u.raw_audio.frame_rate; 117*e92593f4Sbeveloper int out_frames = int(frames); 118*e92593f4Sbeveloper fFractionalFrames += frames - double(out_frames); 119*e92593f4Sbeveloper if (fFractionalFrames >= 1.0) { 120*e92593f4Sbeveloper fFractionalFrames -= 1.0; 1217619f562Sbeveloper out_frames++; 122*e92593f4Sbeveloper } 123*e92593f4Sbeveloper 124*e92593f4Sbeveloper // if fLastDataFrameWritten != -1, then we have a valid last position 125*e92593f4Sbeveloper // and can do glitch compensation 126*e92593f4Sbeveloper if (fLastDataFrameWritten >= 0) { 127*e92593f4Sbeveloper int expected_frame = (fLastDataFrameWritten + 1) % fMixBufferFrameCount; 128*e92593f4Sbeveloper if (offset != expected_frame) { 129*e92593f4Sbeveloper 130*e92593f4Sbeveloper // due to rounding and other errors, offset might be off by +/- 1 131*e92593f4Sbeveloper // this is not really a bad glitch, we just adjust the position 132*e92593f4Sbeveloper 133*e92593f4Sbeveloper if (offset == fLastDataFrameWritten) { 134*e92593f4Sbeveloper //printf("MixerInput::BufferReceived: -1 frame GLITCH! last frame was %ld, expected frame was %d, new frame is %d\n", fLastDataFrameWritten, expected_frame, offset); 135*e92593f4Sbeveloper offset = expected_frame; 136*e92593f4Sbeveloper } else if (offset == ((fLastDataFrameWritten + 2) % fMixBufferFrameCount)) { 137*e92593f4Sbeveloper //printf("MixerInput::BufferReceived: +1 frame GLITCH! last frame was %ld, expected frame was %d, new frame is %d\n", fLastDataFrameWritten, expected_frame, offset); 138*e92593f4Sbeveloper offset = expected_frame; 139*e92593f4Sbeveloper } else { 140*e92593f4Sbeveloper printf("MixerInput::BufferReceived: GLITCH! last frame was %ld, expected frame was %d, new frame is %d\n", fLastDataFrameWritten, expected_frame, offset); 141*e92593f4Sbeveloper 142*e92593f4Sbeveloper if (start > fLastDataAvailableTime) { 143*e92593f4Sbeveloper if ((start - fLastDataAvailableTime) < (buffer_duration / 10)) { 144*e92593f4Sbeveloper // buffer is less than 10% of buffer duration too late 145*e92593f4Sbeveloper printf("short glitch, buffer too late, time delta %Ld\n", start - fLastDataAvailableTime); 146*e92593f4Sbeveloper offset = expected_frame; 147*e92593f4Sbeveloper out_frames++; 148*e92593f4Sbeveloper } else { 149*e92593f4Sbeveloper // buffer more than 10% of buffer duration too late 150*e92593f4Sbeveloper // XXX zerofill buffer 151*e92593f4Sbeveloper printf("MAJOR glitch, buffer too late, time delta %Ld\n", start - fLastDataAvailableTime); 152*e92593f4Sbeveloper } 153*e92593f4Sbeveloper } else { // start <= fLastDataAvailableTime 154*e92593f4Sbeveloper // the new buffer is too early 155*e92593f4Sbeveloper if ((fLastDataAvailableTime - start) < (buffer_duration / 10)) { 156*e92593f4Sbeveloper // buffer is less than 10% of buffer duration too early 157*e92593f4Sbeveloper printf("short glitch, buffer too early, time delta %Ld\n", fLastDataAvailableTime - start); 158*e92593f4Sbeveloper offset = expected_frame; 159*e92593f4Sbeveloper out_frames--; 160*e92593f4Sbeveloper if (out_frames < 1) 161*e92593f4Sbeveloper out_frames = 1; 162*e92593f4Sbeveloper } else { 163*e92593f4Sbeveloper // buffer more than 10% of buffer duration too early 164*e92593f4Sbeveloper // XXX zerofill buffer 165*e92593f4Sbeveloper printf("MAJOR glitch, buffer too early, time delta %Ld\n", fLastDataAvailableTime - start); 166*e92593f4Sbeveloper } 167*e92593f4Sbeveloper } 168*e92593f4Sbeveloper } 169*e92593f4Sbeveloper } 170*e92593f4Sbeveloper } 1717b0daf5cSbeveloper 1728d28117fSbeveloper //printf("data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n", start, start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio)), offset, offset + out_frames); 1738df36cddSbeveloper 1747b0daf5cSbeveloper if (offset + out_frames > fMixBufferFrameCount) { 1757b0daf5cSbeveloper 1767b0daf5cSbeveloper int out_frames1 = fMixBufferFrameCount - offset; 1777b0daf5cSbeveloper int out_frames2 = out_frames - out_frames1; 1787b0daf5cSbeveloper int in_frames1 = (out_frames1 * in_frames) / out_frames; 1797b0daf5cSbeveloper int in_frames2 = in_frames - in_frames1; 1807b0daf5cSbeveloper 181*e92593f4Sbeveloper //printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(), start, start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio)), offset, offset + out_frames1 - 1, 0, out_frames2 - 1); 1827619f562Sbeveloper PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(), start, start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio)), offset, offset + out_frames1 - 1, 0, out_frames2 - 1); 183191033efSbeveloper PRINT(5, " in_frames %5d, out_frames %5d, in_frames1 %5d, out_frames1 %5d, in_frames2 %5d, out_frames2 %5d\n", 184191033efSbeveloper in_frames, out_frames, in_frames1, out_frames1, in_frames2, out_frames2); 1857b0daf5cSbeveloper 186*e92593f4Sbeveloper fLastDataFrameWritten = out_frames2 - 1; 187*e92593f4Sbeveloper 1888d28117fSbeveloper offset *= sizeof(float) * fInputChannelCount; // convert offset from frames into bytes 1898d28117fSbeveloper 1907b0daf5cSbeveloper for (int i = 0; i < fInputChannelCount; i++) { 19178563dcaSbeveloper fResampler[i]->Resample(reinterpret_cast<char *>(data) + i * bytes_per_sample(fInput.format.u.raw_audio), 19278563dcaSbeveloper bytes_per_frame(fInput.format.u.raw_audio), 1937b0daf5cSbeveloper in_frames1, 1948d28117fSbeveloper reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base) + offset, 1957b0daf5cSbeveloper fInputChannelCount * sizeof(float), 1967b0daf5cSbeveloper out_frames1, 1977b0daf5cSbeveloper fInputChannelInfo[i].gain); 1987b0daf5cSbeveloper 1997d970b31Sbeveloper fResampler[i]->Resample(reinterpret_cast<char *>(data) + i * bytes_per_sample(fInput.format.u.raw_audio) + in_frames1 * bytes_per_frame(fInput.format.u.raw_audio), 20078563dcaSbeveloper bytes_per_frame(fInput.format.u.raw_audio), 2017b0daf5cSbeveloper in_frames2, 2027b0daf5cSbeveloper reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base), 2037b0daf5cSbeveloper fInputChannelCount * sizeof(float), 2047b0daf5cSbeveloper out_frames2, 2057b0daf5cSbeveloper fInputChannelInfo[i].gain); 206*e92593f4Sbeveloper 2077b0daf5cSbeveloper } 2087b0daf5cSbeveloper } else { 2097b0daf5cSbeveloper 210*e92593f4Sbeveloper //printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n", fCore->fTimeSource->Now(), start, start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio)), offset, offset + out_frames - 1); 2117619f562Sbeveloper PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n", fCore->fTimeSource->Now(), start, start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio)), offset, offset + out_frames - 1); 212191033efSbeveloper PRINT(5, " in_frames %5d, out_frames %5d\n", in_frames, out_frames); 2138d28117fSbeveloper 214*e92593f4Sbeveloper fLastDataFrameWritten = offset + out_frames - 1; 215*e92593f4Sbeveloper 2168d28117fSbeveloper offset *= sizeof(float) * fInputChannelCount; // convert offset from frames into bytes 2177b0daf5cSbeveloper 2187b0daf5cSbeveloper for (int i = 0; i < fInputChannelCount; i++) { 21978563dcaSbeveloper fResampler[i]->Resample(reinterpret_cast<char *>(data) + i * bytes_per_sample(fInput.format.u.raw_audio), 22078563dcaSbeveloper bytes_per_frame(fInput.format.u.raw_audio), 2217b0daf5cSbeveloper in_frames, 2228d28117fSbeveloper reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base) + offset, 2237b0daf5cSbeveloper fInputChannelCount * sizeof(float), 2247b0daf5cSbeveloper out_frames, 2257b0daf5cSbeveloper fInputChannelInfo[i].gain); 2267b0daf5cSbeveloper } 2277b0daf5cSbeveloper } 228*e92593f4Sbeveloper 229*e92593f4Sbeveloper fLastDataAvailableTime = start + buffer_duration; 230678c2017Sbeveloper } 2317ee2c804Sbeveloper 2327ee2c804Sbeveloper media_input & 2337ee2c804Sbeveloper MixerInput::MediaInput() 2347ee2c804Sbeveloper { 2357ee2c804Sbeveloper return fInput; 2367ee2c804Sbeveloper } 237e6c7c99fSbeveloper 238e6c7c99fSbeveloper int32 239e6c7c99fSbeveloper MixerInput::ID() 240e6c7c99fSbeveloper { 241e6c7c99fSbeveloper return fInput.destination.id; 242e6c7c99fSbeveloper } 243e6c7c99fSbeveloper 244d91580cdSbeveloper int 245fae6ce82Sbeveloper MixerInput::GetInputChannelCount() 246fae6ce82Sbeveloper { 247fae6ce82Sbeveloper return fInputChannelCount; 248fae6ce82Sbeveloper } 249fae6ce82Sbeveloper 2502e9d6607Sbeveloper void 2519c3be6a5Sbeveloper MixerInput::AddInputChannelDestination(int channel, int destination_type) 2522e9d6607Sbeveloper { 2539c3be6a5Sbeveloper uint32 mask = ChannelTypeToChannelMask(destination_type); 254e6c7c99fSbeveloper 2552e9d6607Sbeveloper // test if the channel is valid 2562e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 2572e9d6607Sbeveloper return; 2582e9d6607Sbeveloper 2592e9d6607Sbeveloper // test if it is already set 2609c3be6a5Sbeveloper if (fInputChannelInfo[channel].destination_mask & mask) 2612e9d6607Sbeveloper return; 2622e9d6607Sbeveloper 2639c3be6a5Sbeveloper // verify that no other channel has id 2649c3be6a5Sbeveloper if (-1 != GetInputChannelForDestination(destination_type)) { 2659c3be6a5Sbeveloper ERROR("MixerInput::AddInputChannelDestination: destination_type %d already assigned to channel %d\n", destination_type, GetInputChannelForDestination(destination_type)); 2669c3be6a5Sbeveloper return; 2679c3be6a5Sbeveloper } 2682e9d6607Sbeveloper 2692e9d6607Sbeveloper // add it to specified channel 2709c3be6a5Sbeveloper fInputChannelInfo[channel].destination_mask |= mask; 2712e9d6607Sbeveloper 2729c3be6a5Sbeveloper fUserOverridesChannelDestinations = true; 2739c3be6a5Sbeveloper UpdateInputChannelDestinations(); 2742e9d6607Sbeveloper } 2752e9d6607Sbeveloper 2762e9d6607Sbeveloper void 2779c3be6a5Sbeveloper MixerInput::RemoveInputChannelDestination(int channel, int destination_type) 2782e9d6607Sbeveloper { 2799c3be6a5Sbeveloper uint32 mask = ChannelTypeToChannelMask(destination_type); 2802e9d6607Sbeveloper 2812e9d6607Sbeveloper // test if the channel is valid 2822e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 2832e9d6607Sbeveloper return; 2842e9d6607Sbeveloper 2852e9d6607Sbeveloper // test if it is really set 2869c3be6a5Sbeveloper if ((fInputChannelInfo[channel].destination_mask & mask) == 0) 2872e9d6607Sbeveloper return; 2882e9d6607Sbeveloper 2892e9d6607Sbeveloper // remove it from specified channel 2909c3be6a5Sbeveloper fInputChannelInfo[channel].destination_mask &= ~mask; 2912e9d6607Sbeveloper 2929c3be6a5Sbeveloper fUserOverridesChannelDestinations = true; 2939c3be6a5Sbeveloper UpdateInputChannelDestinations(); 2942e9d6607Sbeveloper } 2952e9d6607Sbeveloper 2969c3be6a5Sbeveloper bool 2979c3be6a5Sbeveloper MixerInput::HasInputChannelDestination(int channel, int destination_type) 2982e9d6607Sbeveloper { 2992e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 3009c3be6a5Sbeveloper return false; 3019c3be6a5Sbeveloper if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 3029c3be6a5Sbeveloper return false; 3039c3be6a5Sbeveloper return fInputChannelInfo[channel].destination_mask & ChannelTypeToChannelMask(destination_type); 3042e9d6607Sbeveloper } 3052e9d6607Sbeveloper 3069c3be6a5Sbeveloper int 3079c3be6a5Sbeveloper MixerInput::GetInputChannelForDestination(int destination_type) 3089c3be6a5Sbeveloper { 3099c3be6a5Sbeveloper if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 3109c3be6a5Sbeveloper return -1; 3119c3be6a5Sbeveloper uint32 mask = ChannelTypeToChannelMask(destination_type); 3129c3be6a5Sbeveloper for (int chan = 0; chan < fInputChannelCount; chan++) { 3139c3be6a5Sbeveloper if (fInputChannelInfo[chan].destination_mask & mask) 3149c3be6a5Sbeveloper return chan; 3159c3be6a5Sbeveloper } 3169c3be6a5Sbeveloper return -1; 3179c3be6a5Sbeveloper } 3189c3be6a5Sbeveloper 3199c3be6a5Sbeveloper int 3202e9d6607Sbeveloper MixerInput::GetInputChannelType(int channel) 3212e9d6607Sbeveloper { 3222e9d6607Sbeveloper // test if the channel is valid 3232e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 3242e9d6607Sbeveloper return 0; 3259c3be6a5Sbeveloper return GetChannelType(channel, fInputChannelMask); 3262e9d6607Sbeveloper } 3272e9d6607Sbeveloper 3282e9d6607Sbeveloper void 3292e9d6607Sbeveloper MixerInput::SetInputChannelGain(int channel, float gain) 3302e9d6607Sbeveloper { 3312e9d6607Sbeveloper // test if the channel is valid 3322e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 3332e9d6607Sbeveloper return; 3342e9d6607Sbeveloper if (gain < 0.0f) 3352e9d6607Sbeveloper gain = 0.0f; 3362e9d6607Sbeveloper 3372e9d6607Sbeveloper fInputChannelInfo[channel].gain = gain; 3382e9d6607Sbeveloper } 3392e9d6607Sbeveloper 3402e9d6607Sbeveloper float 3412e9d6607Sbeveloper MixerInput::GetInputChannelGain(int channel) 3422e9d6607Sbeveloper { 3432e9d6607Sbeveloper // test if the channel is valid 3442e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 3452e9d6607Sbeveloper return 0.0f; 3462e9d6607Sbeveloper return fInputChannelInfo[channel].gain; 3472e9d6607Sbeveloper } 3482e9d6607Sbeveloper 3492e9d6607Sbeveloper void 3509c3be6a5Sbeveloper MixerInput::UpdateInputChannelDestinationMask() 3512e9d6607Sbeveloper { 3522e9d6607Sbeveloper // is the user already messed with the assignmens, don't do anything. 3539c3be6a5Sbeveloper if (fUserOverridesChannelDestinations) 3542e9d6607Sbeveloper return; 3552e9d6607Sbeveloper 3569c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinationMask: enter\n"); 3572e9d6607Sbeveloper 358806cf560Sbeveloper // first apply a 1:1 mapping 3592e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 3609c3be6a5Sbeveloper fInputChannelInfo[i].destination_mask = GetChannelMask(i, fInputChannelMask); 361806cf560Sbeveloper 362806cf560Sbeveloper // specialize this, depending on the available physical output channels 363643e1b2eSbeveloper if (fCore->OutputChannelCount() <= 2) { 364643e1b2eSbeveloper // less or equal two channels 365806cf560Sbeveloper if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { 366ab276ac8Sbeveloper fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO; 367806cf560Sbeveloper } 368643e1b2eSbeveloper } else { 369643e1b2eSbeveloper // more than two channel output card 370806cf560Sbeveloper if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { 371ab276ac8Sbeveloper fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO; 372806cf560Sbeveloper } 373806cf560Sbeveloper if (fInputChannelCount == 2 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) { 3749c3be6a5Sbeveloper fInputChannelInfo[0].destination_mask = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT; 375806cf560Sbeveloper } 376806cf560Sbeveloper if (fInputChannelCount == 2 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) { 3779c3be6a5Sbeveloper fInputChannelInfo[0].destination_mask = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT; 378806cf560Sbeveloper } 379806cf560Sbeveloper if (fInputChannelCount == 2 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) { 3809c3be6a5Sbeveloper fInputChannelInfo[1].destination_mask = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT; 381806cf560Sbeveloper } 382806cf560Sbeveloper if (fInputChannelCount == 2 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) { 3839c3be6a5Sbeveloper fInputChannelInfo[1].destination_mask = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT; 384806cf560Sbeveloper } 3852e9d6607Sbeveloper } 3862e9d6607Sbeveloper 3872e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 388d91580cdSbeveloper TRACE("UpdateInputChannelDestinationMask: input channel %d, destination_mask 0x%08lX, base %p, gain %.3f\n", i, fInputChannelInfo[i].destination_mask, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); 3892e9d6607Sbeveloper 3909c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinationMask: leave\n"); 3912e9d6607Sbeveloper } 3922e9d6607Sbeveloper 3932e9d6607Sbeveloper void 3949c3be6a5Sbeveloper MixerInput::UpdateInputChannelDestinations() 3952e9d6607Sbeveloper { 396d91580cdSbeveloper int channel_count; 3972e9d6607Sbeveloper uint32 all_bits; 3982e9d6607Sbeveloper uint32 mask; 3992e9d6607Sbeveloper 4009c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinations: enter\n"); 4012e9d6607Sbeveloper 4022e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 403d91580cdSbeveloper TRACE("UpdateInputChannelDestinations: input channel %d, destination_mask 0x%08lX, base %p, gain %.3f\n", i, fInputChannelInfo[i].destination_mask, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); 4042e9d6607Sbeveloper 4052e9d6607Sbeveloper all_bits = 0; 4062e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 4079c3be6a5Sbeveloper all_bits |= fInputChannelInfo[i].destination_mask; 4082e9d6607Sbeveloper 409d91580cdSbeveloper TRACE("UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits); 4102e9d6607Sbeveloper 4112e9d6607Sbeveloper channel_count = count_nonzero_bits(all_bits); 4122e9d6607Sbeveloper 413d91580cdSbeveloper TRACE("UpdateInputChannelDestinations: %d input channels, %d mixer channels (%d old)\n", fInputChannelCount, channel_count, fMixerChannelCount); 4142e9d6607Sbeveloper 4152e9d6607Sbeveloper if (channel_count != fMixerChannelCount) { 4169c3be6a5Sbeveloper delete [] fMixerChannelInfo; 4172e9d6607Sbeveloper fMixerChannelInfo = new mixer_chan_info[channel_count]; 4182e9d6607Sbeveloper fMixerChannelCount = channel_count; 4192e9d6607Sbeveloper } 4202e9d6607Sbeveloper 4212e9d6607Sbeveloper // assign each mixer channel one type 4229c3be6a5Sbeveloper // and the gain from the fChannelTypeGain[] 423d91580cdSbeveloper mask = 1; 424d91580cdSbeveloper for (int i = 0; i < fMixerChannelCount; i++) { 4252e9d6607Sbeveloper while (mask != 0 && (all_bits & mask) == 0) 4262e9d6607Sbeveloper mask <<= 1; 4279c3be6a5Sbeveloper fMixerChannelInfo[i].destination_type = ChannelMaskToChannelType(mask); 4289c3be6a5Sbeveloper fMixerChannelInfo[i].destination_gain = fChannelTypeGain[fMixerChannelInfo[i].destination_type]; 4292e9d6607Sbeveloper mask <<= 1; 4302e9d6607Sbeveloper } 4312e9d6607Sbeveloper 4322e9d6607Sbeveloper // assign buffer_base pointer for each mixer channel 4332e9d6607Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) { 4342e9d6607Sbeveloper int j; 4352e9d6607Sbeveloper for (j = 0; j < fInputChannelCount; j++) { 4369c3be6a5Sbeveloper if (fInputChannelInfo[j].destination_mask & ChannelTypeToChannelMask(fMixerChannelInfo[i].destination_type)) { 437d5848e21Sbeveloper fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j] : 0; 4382e9d6607Sbeveloper break; 4392e9d6607Sbeveloper } 4402e9d6607Sbeveloper } 4412e9d6607Sbeveloper if (j == fInputChannelCount) { 442a2ca4723Sbeveloper ERROR("buffer assignment failed for mixer chan %d\n", i); 4432e9d6607Sbeveloper fMixerChannelInfo[i].buffer_base = fMixBuffer; 4442e9d6607Sbeveloper } 4452e9d6607Sbeveloper } 4462e9d6607Sbeveloper 4472e9d6607Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) 4489c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinations: mixer channel %d, type %2d, base %p, gain %.3f\n", i, fMixerChannelInfo[i].destination_type, fMixerChannelInfo[i].buffer_base, fMixerChannelInfo[i].destination_gain); 4492e9d6607Sbeveloper 4509c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinations: leave\n"); 4512e9d6607Sbeveloper } 45269517c15Sbeveloper /* 4532e9d6607Sbeveloper void 4549c3be6a5Sbeveloper MixerInput::SetInputChannelDestinationGain(int channel, int destination_type, float gain) 4552e9d6607Sbeveloper { 4569c3be6a5Sbeveloper TRACE("SetInputChannelDestinationGain: channel %d, destination_type %d, gain %.4f\n", channel, destination_type, gain); 4579c3be6a5Sbeveloper // we don't need the channel, as each destination_type can only exist 4589c3be6a5Sbeveloper // once for each MixerInput, but we use it for parameter validation 4599c3be6a5Sbeveloper // and to have a interface similar to MixerOutput 4602e9d6607Sbeveloper if (channel < 0 || channel >= fMixerChannelCount) 4612e9d6607Sbeveloper return; 4629c3be6a5Sbeveloper if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 4639c3be6a5Sbeveloper return; 4642e9d6607Sbeveloper if (gain < 0.0f) 4652e9d6607Sbeveloper gain = 0.0f; 4669c3be6a5Sbeveloper fChannelTypeGain[destination_type] = gain; 4679c3be6a5Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) { 4689c3be6a5Sbeveloper if (fMixerChannelInfo[i].destination_type == destination_type) { 4699c3be6a5Sbeveloper fMixerChannelInfo[i].destination_gain = gain; 4709c3be6a5Sbeveloper return; 4719c3be6a5Sbeveloper } 4729c3be6a5Sbeveloper } 4732e9d6607Sbeveloper } 4742e9d6607Sbeveloper 4752e9d6607Sbeveloper float 4769c3be6a5Sbeveloper MixerInput::GetInputChannelDestinationGain(int channel, int destination_type) 4772e9d6607Sbeveloper { 4789c3be6a5Sbeveloper // we don't need the channel, as each destination_type can only exist 4799c3be6a5Sbeveloper // once for each MixerInput, but we use it for parameter validation 4809c3be6a5Sbeveloper // and to have a interface similar to MixerOutput 4812e9d6607Sbeveloper if (channel < 0 || channel >= fMixerChannelCount) 4829c3be6a5Sbeveloper return 0.0f; 4839c3be6a5Sbeveloper if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 4849c3be6a5Sbeveloper return 0.0f; 4859c3be6a5Sbeveloper return fChannelTypeGain[destination_type]; 4862e9d6607Sbeveloper } 48769517c15Sbeveloper */ 48869517c15Sbeveloper 48969517c15Sbeveloper void 49069517c15Sbeveloper MixerInput::SetMixerChannelGain(int mixer_channel, float gain) 49169517c15Sbeveloper { 49269517c15Sbeveloper if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 49369517c15Sbeveloper return; 49469517c15Sbeveloper if (gain < 0.0f) 49569517c15Sbeveloper gain = 0.0f; 49669517c15Sbeveloper 49769517c15Sbeveloper fMixerChannelInfo[mixer_channel].destination_gain = gain; 49869517c15Sbeveloper fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain; 49969517c15Sbeveloper } 50069517c15Sbeveloper 50169517c15Sbeveloper float 50269517c15Sbeveloper MixerInput::GetMixerChannelGain(int mixer_channel) 50369517c15Sbeveloper { 50469517c15Sbeveloper if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 50569517c15Sbeveloper return 0.0; 50669517c15Sbeveloper return fMixerChannelInfo[mixer_channel].destination_gain; 50769517c15Sbeveloper } 50869517c15Sbeveloper 50969517c15Sbeveloper int 51069517c15Sbeveloper MixerInput::GetMixerChannelType(int mixer_channel) 51169517c15Sbeveloper { 51269517c15Sbeveloper if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 51369517c15Sbeveloper return -1; 51469517c15Sbeveloper return fMixerChannelInfo[mixer_channel].destination_type; 51569517c15Sbeveloper } 5162e9d6607Sbeveloper 5172e9d6607Sbeveloper void 5181c237c18Sbeveloper MixerInput::SetEnabled(bool yesno) 5191c237c18Sbeveloper { 5201c237c18Sbeveloper fEnabled = yesno; 5211c237c18Sbeveloper } 5221c237c18Sbeveloper 5231c237c18Sbeveloper bool 5241c237c18Sbeveloper MixerInput::IsEnabled() 5251c237c18Sbeveloper { 5261c237c18Sbeveloper return fEnabled; 5271c237c18Sbeveloper } 5281c237c18Sbeveloper 5291c237c18Sbeveloper void 5308d28117fSbeveloper MixerInput::SetMixBufferFormat(int32 framerate, int32 frames) 5312e9d6607Sbeveloper { 532a2ca4723Sbeveloper TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n", framerate, frames); 533d5848e21Sbeveloper 5347b0daf5cSbeveloper fMixBufferFrameRate = framerate; 5358df36cddSbeveloper debugMixBufferFrames = frames; 5362e9d6607Sbeveloper 537d5848e21Sbeveloper // frames and/or framerate can be 0 (if no output is connected) 538d5848e21Sbeveloper if (framerate == 0 || frames == 0) { 539d5848e21Sbeveloper if (fMixBuffer) { 540d5848e21Sbeveloper rtm_free(fMixBuffer); 541d5848e21Sbeveloper fMixBuffer = 0; 542d5848e21Sbeveloper } 543d5848e21Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 544d5848e21Sbeveloper fInputChannelInfo[i].buffer_base = 0; 545d5848e21Sbeveloper fMixBufferFrameCount = 0; 546d5848e21Sbeveloper 5479c3be6a5Sbeveloper UpdateInputChannelDestinationMask(); 5489c3be6a5Sbeveloper UpdateInputChannelDestinations(); 549d5848e21Sbeveloper return; 550d5848e21Sbeveloper } 5517b0daf5cSbeveloper 5527b0daf5cSbeveloper // make fMixBufferFrameCount an integral multiple of frames, 5537b0daf5cSbeveloper // but at least 3 times duration of our input buffer 5547b0daf5cSbeveloper // and at least 2 times duration of the output buffer 5557b0daf5cSbeveloper bigtime_t inputBufferLength = duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio)); 5567b0daf5cSbeveloper bigtime_t outputBufferLength = duration_for_frames(framerate, frames); 5577b0daf5cSbeveloper bigtime_t mixerBufferLength = max_c(3 * inputBufferLength, 2 * outputBufferLength); 5587b0daf5cSbeveloper int temp = frames_for_duration(framerate, mixerBufferLength); 5597b0daf5cSbeveloper fMixBufferFrameCount = ((temp / frames) + 1) * frames; 5607b0daf5cSbeveloper 561a2ca4723Sbeveloper TRACE(" inputBufferLength %10Ld\n", inputBufferLength); 562a2ca4723Sbeveloper TRACE(" outputBufferLength %10Ld\n", outputBufferLength); 563a2ca4723Sbeveloper TRACE(" mixerBufferLength %10Ld\n", mixerBufferLength); 564d91580cdSbeveloper TRACE(" fMixBufferFrameCount %10d\n", fMixBufferFrameCount); 5657b0daf5cSbeveloper 5668d28117fSbeveloper ASSERT((fMixBufferFrameCount % frames) == 0); 5678d28117fSbeveloper 568*e92593f4Sbeveloper fLastDataFrameWritten = -1; 569*e92593f4Sbeveloper fFractionalFrames = 0.0; 570*e92593f4Sbeveloper 5712e9d6607Sbeveloper if (fMixBuffer) 5722e9d6607Sbeveloper rtm_free(fMixBuffer); 573356855c3Sbeveloper if (fRtmPool) 574356855c3Sbeveloper rtm_delete_pool(fRtmPool); 5757b0daf5cSbeveloper int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount; 576356855c3Sbeveloper if (B_OK != rtm_create_pool(&fRtmPool, size)) 577356855c3Sbeveloper fRtmPool = 0; 578356855c3Sbeveloper fMixBuffer = (float *)rtm_alloc(fRtmPool, size); 5797b0daf5cSbeveloper ASSERT(fMixBuffer); 5807b0daf5cSbeveloper 5817b0daf5cSbeveloper memset(fMixBuffer, 0, size); 5822e9d6607Sbeveloper 5832e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 5847b0daf5cSbeveloper fInputChannelInfo[i].buffer_base = &fMixBuffer[i]; 585d5848e21Sbeveloper 5869c3be6a5Sbeveloper UpdateInputChannelDestinationMask(); 5879c3be6a5Sbeveloper UpdateInputChannelDestinations(); 5882e9d6607Sbeveloper } 589