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), 24af8d0a4dSbeveloper fLastDataAvailableTime(-1), 257b0daf5cSbeveloper fResampler(0), 26356855c3Sbeveloper fRtmPool(0), 279c3be6a5Sbeveloper fUserOverridesChannelDestinations(false) 28678c2017Sbeveloper { 29e6c7c99fSbeveloper fix_multiaudio_format(&fInput.format.u.raw_audio); 30e6c7c99fSbeveloper PRINT_INPUT("MixerInput::MixerInput", fInput); 31e6c7c99fSbeveloper PRINT_CHANNEL_MASK(fInput.format); 322e9d6607Sbeveloper 332e9d6607Sbeveloper ASSERT(fInput.format.u.raw_audio.channel_count > 0); 342e9d6607Sbeveloper 359c3be6a5Sbeveloper for (int i = 0; i < MAX_CHANNEL_TYPES; i++) 369c3be6a5Sbeveloper fChannelTypeGain[i] = 1.0f; 379c3be6a5Sbeveloper 382e9d6607Sbeveloper fInputChannelCount = fInput.format.u.raw_audio.channel_count; 392e9d6607Sbeveloper fInputChannelMask = fInput.format.u.raw_audio.channel_mask; 402e9d6607Sbeveloper fInputChannelInfo = new input_chan_info[fInputChannelCount]; 412e9d6607Sbeveloper 4288777023Sbeveloper // perhaps we need byte swapping 4388777023Sbeveloper if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) { 4488777023Sbeveloper if ( fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT 4588777023Sbeveloper || fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT 4688777023Sbeveloper || fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) { 4788777023Sbeveloper fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format); 4888777023Sbeveloper } 4988777023Sbeveloper } 5088777023Sbeveloper 512e9d6607Sbeveloper // initialize fInputChannelInfo 522e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) { 532e9d6607Sbeveloper fInputChannelInfo[i].buffer_base = 0; // will be set by SetMixBufferFormat() 549c3be6a5Sbeveloper fInputChannelInfo[i].destination_mask = 0; // will be set by UpdateInputChannelDestinationMask() 552e9d6607Sbeveloper fInputChannelInfo[i].gain = 1.0; 562e9d6607Sbeveloper } 572e9d6607Sbeveloper 587b0daf5cSbeveloper // create resamplers 597b0daf5cSbeveloper fResampler = new Resampler * [fInputChannelCount]; 607b0daf5cSbeveloper for (int i = 0; i < fInputChannelCount; i++) 617b0daf5cSbeveloper fResampler[i] = new Resampler(fInput.format.u.raw_audio.format, media_raw_audio_format::B_AUDIO_FLOAT); 627b0daf5cSbeveloper 639c3be6a5Sbeveloper // fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateInputChannelDestinations() 642e9d6607Sbeveloper 658d28117fSbeveloper SetMixBufferFormat(mixFrameRate, mixFrameCount); 66678c2017Sbeveloper } 67678c2017Sbeveloper 68678c2017Sbeveloper MixerInput::~MixerInput() 69678c2017Sbeveloper { 702e9d6607Sbeveloper if (fMixBuffer) 712e9d6607Sbeveloper rtm_free(fMixBuffer); 72356855c3Sbeveloper if (fRtmPool) 73356855c3Sbeveloper rtm_delete_pool(fRtmPool); 742e9d6607Sbeveloper delete [] fInputChannelInfo; 752e9d6607Sbeveloper delete [] fMixerChannelInfo; 767b0daf5cSbeveloper 777b0daf5cSbeveloper // delete resamplers 787b0daf5cSbeveloper for (int i = 0; i < fInputChannelCount; i++) 797b0daf5cSbeveloper delete fResampler[i]; 807b0daf5cSbeveloper delete [] fResampler; 81678c2017Sbeveloper } 82678c2017Sbeveloper 83678c2017Sbeveloper void 84678c2017Sbeveloper MixerInput::BufferReceived(BBuffer *buffer) 85678c2017Sbeveloper { 8688777023Sbeveloper void *data; 8788777023Sbeveloper size_t size; 8888777023Sbeveloper bigtime_t start; 8988777023Sbeveloper 90d5848e21Sbeveloper if (!fMixBuffer) { 91a2ca4723Sbeveloper ERROR("MixerInput::BufferReceived: dropped incoming buffer as we don't have a mix buffer\n"); 92d5848e21Sbeveloper return; 93d5848e21Sbeveloper } 942e9d6607Sbeveloper 9588777023Sbeveloper data = buffer->Data(); 9688777023Sbeveloper size = buffer->SizeUsed(); 9788777023Sbeveloper start = buffer->Header()->start_time; 988d28117fSbeveloper if (start < 0) { 99a2ca4723Sbeveloper ERROR("MixerInput::BufferReceived: buffer with negative start time of %Ld dropped\n", start); 1008d28117fSbeveloper return; 1018d28117fSbeveloper } 10288777023Sbeveloper 103af8d0a4dSbeveloper fLastDataAvailableTime = start + buffer_duration(fInput.format.u.raw_audio); 104af8d0a4dSbeveloper 10588777023Sbeveloper // swap the byte order of this buffer, if necessary 10688777023Sbeveloper if (fInputByteSwap) 10788777023Sbeveloper fInputByteSwap->Swap(data, size); 10888777023Sbeveloper 1098d28117fSbeveloper int32 offset = frames_for_duration(fMixBufferFrameRate, start) % fMixBufferFrameCount; 1108d28117fSbeveloper 111191033efSbeveloper PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n", start, offset); 1127b0daf5cSbeveloper 113191033efSbeveloper int in_frames = size / bytes_per_frame(fInput.format.u.raw_audio); 1147619f562Sbeveloper int out_frames = int((in_frames * fMixBufferFrameRate) / fInput.format.u.raw_audio.frame_rate); // XXX losing fractions 1157619f562Sbeveloper // XXX we should better accumulate the fractions from previous buffers, and also check previous end offset 1167619f562Sbeveloper // XXX to only add an output frame if needed (but we also need to use arrival times to cope with lost buffers). 1177619f562Sbeveloper // XXX This workaround will very often (but not always) cause the first sample of the next buffer to overwrite 1187619f562Sbeveloper // XXX the last sample of the current buffer (but that's better then having some random data at that place) 1197619f562Sbeveloper if (fMixBufferFrameRate % int(0.5 + fInput.format.u.raw_audio.frame_rate) != 0) 1207619f562Sbeveloper out_frames++; 1217b0daf5cSbeveloper 1228d28117fSbeveloper //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); 1238df36cddSbeveloper 1247b0daf5cSbeveloper if (offset + out_frames > fMixBufferFrameCount) { 1257b0daf5cSbeveloper 1267b0daf5cSbeveloper int out_frames1 = fMixBufferFrameCount - offset; 1277b0daf5cSbeveloper int out_frames2 = out_frames - out_frames1; 1287b0daf5cSbeveloper int in_frames1 = (out_frames1 * in_frames) / out_frames; 1297b0daf5cSbeveloper int in_frames2 = in_frames - in_frames1; 1307b0daf5cSbeveloper 1317619f562Sbeveloper 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); 1328df36cddSbeveloper 133191033efSbeveloper PRINT(5, " in_frames %5d, out_frames %5d, in_frames1 %5d, out_frames1 %5d, in_frames2 %5d, out_frames2 %5d\n", 134191033efSbeveloper in_frames, out_frames, in_frames1, out_frames1, in_frames2, out_frames2); 1357b0daf5cSbeveloper 1368d28117fSbeveloper offset *= sizeof(float) * fInputChannelCount; // convert offset from frames into bytes 1378d28117fSbeveloper 1387b0daf5cSbeveloper for (int i = 0; i < fInputChannelCount; i++) { 13978563dcaSbeveloper fResampler[i]->Resample(reinterpret_cast<char *>(data) + i * bytes_per_sample(fInput.format.u.raw_audio), 14078563dcaSbeveloper bytes_per_frame(fInput.format.u.raw_audio), 1417b0daf5cSbeveloper in_frames1, 1428d28117fSbeveloper reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base) + offset, 1437b0daf5cSbeveloper fInputChannelCount * sizeof(float), 1447b0daf5cSbeveloper out_frames1, 1457b0daf5cSbeveloper fInputChannelInfo[i].gain); 1467b0daf5cSbeveloper 1477d970b31Sbeveloper 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), 14878563dcaSbeveloper bytes_per_frame(fInput.format.u.raw_audio), 1497b0daf5cSbeveloper in_frames2, 1507b0daf5cSbeveloper reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base), 1517b0daf5cSbeveloper fInputChannelCount * sizeof(float), 1527b0daf5cSbeveloper out_frames2, 1537b0daf5cSbeveloper fInputChannelInfo[i].gain); 1547b0daf5cSbeveloper } 1557b0daf5cSbeveloper } else { 1567b0daf5cSbeveloper 1577619f562Sbeveloper 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); 158191033efSbeveloper PRINT(5, " in_frames %5d, out_frames %5d\n", in_frames, out_frames); 1598d28117fSbeveloper 1608d28117fSbeveloper offset *= sizeof(float) * fInputChannelCount; // convert offset from frames into bytes 1617b0daf5cSbeveloper 1627b0daf5cSbeveloper for (int i = 0; i < fInputChannelCount; i++) { 16378563dcaSbeveloper fResampler[i]->Resample(reinterpret_cast<char *>(data) + i * bytes_per_sample(fInput.format.u.raw_audio), 16478563dcaSbeveloper bytes_per_frame(fInput.format.u.raw_audio), 1657b0daf5cSbeveloper in_frames, 1668d28117fSbeveloper reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base) + offset, 1677b0daf5cSbeveloper fInputChannelCount * sizeof(float), 1687b0daf5cSbeveloper out_frames, 1697b0daf5cSbeveloper fInputChannelInfo[i].gain); 1707b0daf5cSbeveloper } 1717b0daf5cSbeveloper } 172678c2017Sbeveloper } 1737ee2c804Sbeveloper 1747ee2c804Sbeveloper media_input & 1757ee2c804Sbeveloper MixerInput::MediaInput() 1767ee2c804Sbeveloper { 1777ee2c804Sbeveloper return fInput; 1787ee2c804Sbeveloper } 179e6c7c99fSbeveloper 180e6c7c99fSbeveloper int32 181e6c7c99fSbeveloper MixerInput::ID() 182e6c7c99fSbeveloper { 183e6c7c99fSbeveloper return fInput.destination.id; 184e6c7c99fSbeveloper } 185e6c7c99fSbeveloper 186fae6ce82Sbeveloper uint32 187fae6ce82Sbeveloper MixerInput::GetInputChannelCount() 188fae6ce82Sbeveloper { 189fae6ce82Sbeveloper return fInputChannelCount; 190fae6ce82Sbeveloper } 191fae6ce82Sbeveloper 1922e9d6607Sbeveloper void 1939c3be6a5Sbeveloper MixerInput::AddInputChannelDestination(int channel, int destination_type) 1942e9d6607Sbeveloper { 1959c3be6a5Sbeveloper uint32 mask = ChannelTypeToChannelMask(destination_type); 196e6c7c99fSbeveloper 1972e9d6607Sbeveloper // test if the channel is valid 1982e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 1992e9d6607Sbeveloper return; 2002e9d6607Sbeveloper 2012e9d6607Sbeveloper // test if it is already set 2029c3be6a5Sbeveloper if (fInputChannelInfo[channel].destination_mask & mask) 2032e9d6607Sbeveloper return; 2042e9d6607Sbeveloper 2059c3be6a5Sbeveloper // verify that no other channel has id 2069c3be6a5Sbeveloper if (-1 != GetInputChannelForDestination(destination_type)) { 2079c3be6a5Sbeveloper ERROR("MixerInput::AddInputChannelDestination: destination_type %d already assigned to channel %d\n", destination_type, GetInputChannelForDestination(destination_type)); 2089c3be6a5Sbeveloper return; 2099c3be6a5Sbeveloper } 2102e9d6607Sbeveloper 2112e9d6607Sbeveloper // add it to specified channel 2129c3be6a5Sbeveloper fInputChannelInfo[channel].destination_mask |= mask; 2132e9d6607Sbeveloper 2149c3be6a5Sbeveloper fUserOverridesChannelDestinations = true; 2159c3be6a5Sbeveloper UpdateInputChannelDestinations(); 2162e9d6607Sbeveloper } 2172e9d6607Sbeveloper 2182e9d6607Sbeveloper void 2199c3be6a5Sbeveloper MixerInput::RemoveInputChannelDestination(int channel, int destination_type) 2202e9d6607Sbeveloper { 2219c3be6a5Sbeveloper uint32 mask = ChannelTypeToChannelMask(destination_type); 2222e9d6607Sbeveloper 2232e9d6607Sbeveloper // test if the channel is valid 2242e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 2252e9d6607Sbeveloper return; 2262e9d6607Sbeveloper 2272e9d6607Sbeveloper // test if it is really set 2289c3be6a5Sbeveloper if ((fInputChannelInfo[channel].destination_mask & mask) == 0) 2292e9d6607Sbeveloper return; 2302e9d6607Sbeveloper 2312e9d6607Sbeveloper // remove it from specified channel 2329c3be6a5Sbeveloper fInputChannelInfo[channel].destination_mask &= ~mask; 2332e9d6607Sbeveloper 2349c3be6a5Sbeveloper fUserOverridesChannelDestinations = true; 2359c3be6a5Sbeveloper UpdateInputChannelDestinations(); 2362e9d6607Sbeveloper } 2372e9d6607Sbeveloper 2389c3be6a5Sbeveloper bool 2399c3be6a5Sbeveloper MixerInput::HasInputChannelDestination(int channel, int destination_type) 2402e9d6607Sbeveloper { 2412e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 2429c3be6a5Sbeveloper return false; 2439c3be6a5Sbeveloper if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 2449c3be6a5Sbeveloper return false; 2459c3be6a5Sbeveloper return fInputChannelInfo[channel].destination_mask & ChannelTypeToChannelMask(destination_type); 2462e9d6607Sbeveloper } 2472e9d6607Sbeveloper 2489c3be6a5Sbeveloper int 2499c3be6a5Sbeveloper MixerInput::GetInputChannelForDestination(int destination_type) 2509c3be6a5Sbeveloper { 2519c3be6a5Sbeveloper if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 2529c3be6a5Sbeveloper return -1; 2539c3be6a5Sbeveloper uint32 mask = ChannelTypeToChannelMask(destination_type); 2549c3be6a5Sbeveloper for (int chan = 0; chan < fInputChannelCount; chan++) { 2559c3be6a5Sbeveloper if (fInputChannelInfo[chan].destination_mask & mask) 2569c3be6a5Sbeveloper return chan; 2579c3be6a5Sbeveloper } 2589c3be6a5Sbeveloper return -1; 2599c3be6a5Sbeveloper } 2609c3be6a5Sbeveloper 2619c3be6a5Sbeveloper int 2622e9d6607Sbeveloper MixerInput::GetInputChannelType(int channel) 2632e9d6607Sbeveloper { 2642e9d6607Sbeveloper // test if the channel is valid 2652e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 2662e9d6607Sbeveloper return 0; 2679c3be6a5Sbeveloper return GetChannelType(channel, fInputChannelMask); 2682e9d6607Sbeveloper } 2692e9d6607Sbeveloper 27069517c15Sbeveloper /* 2712e9d6607Sbeveloper void 2722e9d6607Sbeveloper MixerInput::SetInputChannelGain(int channel, float gain) 2732e9d6607Sbeveloper { 2742e9d6607Sbeveloper // test if the channel is valid 2752e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 2762e9d6607Sbeveloper return; 2772e9d6607Sbeveloper if (gain < 0.0f) 2782e9d6607Sbeveloper gain = 0.0f; 2792e9d6607Sbeveloper 2802e9d6607Sbeveloper fInputChannelInfo[channel].gain = gain; 2812e9d6607Sbeveloper } 2822e9d6607Sbeveloper 2832e9d6607Sbeveloper float 2842e9d6607Sbeveloper MixerInput::GetInputChannelGain(int channel) 2852e9d6607Sbeveloper { 2862e9d6607Sbeveloper // test if the channel is valid 2872e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 2882e9d6607Sbeveloper return 0.0f; 2892e9d6607Sbeveloper return fInputChannelInfo[channel].gain; 2902e9d6607Sbeveloper } 29169517c15Sbeveloper */ 2922e9d6607Sbeveloper 2932e9d6607Sbeveloper void 2949c3be6a5Sbeveloper MixerInput::UpdateInputChannelDestinationMask() 2952e9d6607Sbeveloper { 2962e9d6607Sbeveloper // is the user already messed with the assignmens, don't do anything. 2979c3be6a5Sbeveloper if (fUserOverridesChannelDestinations) 2982e9d6607Sbeveloper return; 2992e9d6607Sbeveloper 3009c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinationMask: enter\n"); 3012e9d6607Sbeveloper 302806cf560Sbeveloper // first apply a 1:1 mapping 3032e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 3049c3be6a5Sbeveloper fInputChannelInfo[i].destination_mask = GetChannelMask(i, fInputChannelMask); 305806cf560Sbeveloper 306806cf560Sbeveloper // specialize this, depending on the available physical output channels 307806cf560Sbeveloper switch (fCore->OutputChannelCount()) { 308806cf560Sbeveloper case 0: 309806cf560Sbeveloper case 1: 310806cf560Sbeveloper break; 311806cf560Sbeveloper 312806cf560Sbeveloper case 2: 313806cf560Sbeveloper if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { 314*ab276ac8Sbeveloper fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO; 315806cf560Sbeveloper } 316806cf560Sbeveloper break; 317806cf560Sbeveloper 318806cf560Sbeveloper default: 319806cf560Sbeveloper if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { 320*ab276ac8Sbeveloper fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO; 321806cf560Sbeveloper } 322806cf560Sbeveloper if (fInputChannelCount == 2 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) { 3239c3be6a5Sbeveloper fInputChannelInfo[0].destination_mask = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT; 324806cf560Sbeveloper } 325806cf560Sbeveloper if (fInputChannelCount == 2 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) { 3269c3be6a5Sbeveloper fInputChannelInfo[0].destination_mask = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT; 327806cf560Sbeveloper } 328806cf560Sbeveloper if (fInputChannelCount == 2 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) { 3299c3be6a5Sbeveloper fInputChannelInfo[1].destination_mask = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT; 330806cf560Sbeveloper } 331806cf560Sbeveloper if (fInputChannelCount == 2 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) { 3329c3be6a5Sbeveloper fInputChannelInfo[1].destination_mask = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT; 333806cf560Sbeveloper } 334806cf560Sbeveloper break; 3352e9d6607Sbeveloper } 3362e9d6607Sbeveloper 3372e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 3389c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinationMask: input channel %d, destination_mask 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].destination_mask, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); 3392e9d6607Sbeveloper 3409c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinationMask: leave\n"); 3412e9d6607Sbeveloper } 3422e9d6607Sbeveloper 3432e9d6607Sbeveloper void 3449c3be6a5Sbeveloper MixerInput::UpdateInputChannelDestinations() 3452e9d6607Sbeveloper { 3462e9d6607Sbeveloper uint32 channel_count; 3472e9d6607Sbeveloper uint32 all_bits; 3482e9d6607Sbeveloper uint32 mask; 3492e9d6607Sbeveloper 3509c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinations: enter\n"); 3512e9d6607Sbeveloper 3522e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 3539c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinations: input channel %d, destination_mask 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].destination_mask, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); 3542e9d6607Sbeveloper 3552e9d6607Sbeveloper all_bits = 0; 3562e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 3579c3be6a5Sbeveloper all_bits |= fInputChannelInfo[i].destination_mask; 3582e9d6607Sbeveloper 3599c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinations: all_bits = %08x\n", all_bits); 3602e9d6607Sbeveloper 3612e9d6607Sbeveloper channel_count = count_nonzero_bits(all_bits); 3622e9d6607Sbeveloper 3639c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinations: %ld input channels, %ld mixer channels (%ld old)\n", fInputChannelCount, channel_count, fMixerChannelCount); 3642e9d6607Sbeveloper 3652e9d6607Sbeveloper if (channel_count != fMixerChannelCount) { 3669c3be6a5Sbeveloper delete [] fMixerChannelInfo; 3672e9d6607Sbeveloper fMixerChannelInfo = new mixer_chan_info[channel_count]; 3682e9d6607Sbeveloper fMixerChannelCount = channel_count; 3692e9d6607Sbeveloper } 3702e9d6607Sbeveloper 3712e9d6607Sbeveloper // assign each mixer channel one type 3729c3be6a5Sbeveloper // and the gain from the fChannelTypeGain[] 3732e9d6607Sbeveloper for (int i = 0, mask = 1; i < fMixerChannelCount; i++) { 3742e9d6607Sbeveloper while (mask != 0 && (all_bits & mask) == 0) 3752e9d6607Sbeveloper mask <<= 1; 3769c3be6a5Sbeveloper fMixerChannelInfo[i].destination_type = ChannelMaskToChannelType(mask); 3779c3be6a5Sbeveloper fMixerChannelInfo[i].destination_gain = fChannelTypeGain[fMixerChannelInfo[i].destination_type]; 3782e9d6607Sbeveloper mask <<= 1; 3792e9d6607Sbeveloper } 3802e9d6607Sbeveloper 3812e9d6607Sbeveloper // assign buffer_base pointer for each mixer channel 3822e9d6607Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) { 3832e9d6607Sbeveloper int j; 3842e9d6607Sbeveloper for (j = 0; j < fInputChannelCount; j++) { 3859c3be6a5Sbeveloper if (fInputChannelInfo[j].destination_mask & ChannelTypeToChannelMask(fMixerChannelInfo[i].destination_type)) { 386d5848e21Sbeveloper fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j] : 0; 3872e9d6607Sbeveloper break; 3882e9d6607Sbeveloper } 3892e9d6607Sbeveloper } 3902e9d6607Sbeveloper if (j == fInputChannelCount) { 391a2ca4723Sbeveloper ERROR("buffer assignment failed for mixer chan %d\n", i); 3922e9d6607Sbeveloper fMixerChannelInfo[i].buffer_base = fMixBuffer; 3932e9d6607Sbeveloper } 3942e9d6607Sbeveloper } 3952e9d6607Sbeveloper 3962e9d6607Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) 3979c3be6a5Sbeveloper 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); 3982e9d6607Sbeveloper 3999c3be6a5Sbeveloper TRACE("UpdateInputChannelDestinations: leave\n"); 4002e9d6607Sbeveloper } 40169517c15Sbeveloper /* 4022e9d6607Sbeveloper void 4039c3be6a5Sbeveloper MixerInput::SetInputChannelDestinationGain(int channel, int destination_type, float gain) 4042e9d6607Sbeveloper { 4059c3be6a5Sbeveloper TRACE("SetInputChannelDestinationGain: channel %d, destination_type %d, gain %.4f\n", channel, destination_type, gain); 4069c3be6a5Sbeveloper // we don't need the channel, as each destination_type can only exist 4079c3be6a5Sbeveloper // once for each MixerInput, but we use it for parameter validation 4089c3be6a5Sbeveloper // and to have a interface similar to MixerOutput 4092e9d6607Sbeveloper if (channel < 0 || channel >= fMixerChannelCount) 4102e9d6607Sbeveloper return; 4119c3be6a5Sbeveloper if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 4129c3be6a5Sbeveloper return; 4132e9d6607Sbeveloper if (gain < 0.0f) 4142e9d6607Sbeveloper gain = 0.0f; 4159c3be6a5Sbeveloper fChannelTypeGain[destination_type] = gain; 4169c3be6a5Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) { 4179c3be6a5Sbeveloper if (fMixerChannelInfo[i].destination_type == destination_type) { 4189c3be6a5Sbeveloper fMixerChannelInfo[i].destination_gain = gain; 4199c3be6a5Sbeveloper return; 4209c3be6a5Sbeveloper } 4219c3be6a5Sbeveloper } 4222e9d6607Sbeveloper } 4232e9d6607Sbeveloper 4242e9d6607Sbeveloper float 4259c3be6a5Sbeveloper MixerInput::GetInputChannelDestinationGain(int channel, int destination_type) 4262e9d6607Sbeveloper { 4279c3be6a5Sbeveloper // we don't need the channel, as each destination_type can only exist 4289c3be6a5Sbeveloper // once for each MixerInput, but we use it for parameter validation 4299c3be6a5Sbeveloper // and to have a interface similar to MixerOutput 4302e9d6607Sbeveloper if (channel < 0 || channel >= fMixerChannelCount) 4319c3be6a5Sbeveloper return 0.0f; 4329c3be6a5Sbeveloper if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 4339c3be6a5Sbeveloper return 0.0f; 4349c3be6a5Sbeveloper return fChannelTypeGain[destination_type]; 4352e9d6607Sbeveloper } 43669517c15Sbeveloper */ 43769517c15Sbeveloper 43869517c15Sbeveloper void 43969517c15Sbeveloper MixerInput::SetMixerChannelGain(int mixer_channel, float gain) 44069517c15Sbeveloper { 44169517c15Sbeveloper if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 44269517c15Sbeveloper return; 44369517c15Sbeveloper if (gain < 0.0f) 44469517c15Sbeveloper gain = 0.0f; 44569517c15Sbeveloper 44669517c15Sbeveloper fMixerChannelInfo[mixer_channel].destination_gain = gain; 44769517c15Sbeveloper fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain; 44869517c15Sbeveloper } 44969517c15Sbeveloper 45069517c15Sbeveloper float 45169517c15Sbeveloper MixerInput::GetMixerChannelGain(int mixer_channel) 45269517c15Sbeveloper { 45369517c15Sbeveloper if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 45469517c15Sbeveloper return 0.0; 45569517c15Sbeveloper return fMixerChannelInfo[mixer_channel].destination_gain; 45669517c15Sbeveloper } 45769517c15Sbeveloper 45869517c15Sbeveloper int 45969517c15Sbeveloper MixerInput::GetMixerChannelType(int mixer_channel) 46069517c15Sbeveloper { 46169517c15Sbeveloper if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 46269517c15Sbeveloper return -1; 46369517c15Sbeveloper return fMixerChannelInfo[mixer_channel].destination_type; 46469517c15Sbeveloper } 4652e9d6607Sbeveloper 4662e9d6607Sbeveloper void 4671c237c18Sbeveloper MixerInput::SetEnabled(bool yesno) 4681c237c18Sbeveloper { 4691c237c18Sbeveloper fEnabled = yesno; 4701c237c18Sbeveloper } 4711c237c18Sbeveloper 4721c237c18Sbeveloper bool 4731c237c18Sbeveloper MixerInput::IsEnabled() 4741c237c18Sbeveloper { 4751c237c18Sbeveloper return fEnabled; 4761c237c18Sbeveloper } 4771c237c18Sbeveloper 4781c237c18Sbeveloper void 4798d28117fSbeveloper MixerInput::SetMixBufferFormat(int32 framerate, int32 frames) 4802e9d6607Sbeveloper { 481a2ca4723Sbeveloper TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n", framerate, frames); 482d5848e21Sbeveloper 4837b0daf5cSbeveloper fMixBufferFrameRate = framerate; 4848df36cddSbeveloper debugMixBufferFrames = frames; 4852e9d6607Sbeveloper 486d5848e21Sbeveloper // frames and/or framerate can be 0 (if no output is connected) 487d5848e21Sbeveloper if (framerate == 0 || frames == 0) { 488d5848e21Sbeveloper if (fMixBuffer) { 489d5848e21Sbeveloper rtm_free(fMixBuffer); 490d5848e21Sbeveloper fMixBuffer = 0; 491d5848e21Sbeveloper } 492d5848e21Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 493d5848e21Sbeveloper fInputChannelInfo[i].buffer_base = 0; 494d5848e21Sbeveloper fMixBufferFrameCount = 0; 495d5848e21Sbeveloper 4969c3be6a5Sbeveloper UpdateInputChannelDestinationMask(); 4979c3be6a5Sbeveloper UpdateInputChannelDestinations(); 498d5848e21Sbeveloper return; 499d5848e21Sbeveloper } 5007b0daf5cSbeveloper 5017b0daf5cSbeveloper // make fMixBufferFrameCount an integral multiple of frames, 5027b0daf5cSbeveloper // but at least 3 times duration of our input buffer 5037b0daf5cSbeveloper // and at least 2 times duration of the output buffer 5047b0daf5cSbeveloper bigtime_t inputBufferLength = duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio)); 5057b0daf5cSbeveloper bigtime_t outputBufferLength = duration_for_frames(framerate, frames); 5067b0daf5cSbeveloper bigtime_t mixerBufferLength = max_c(3 * inputBufferLength, 2 * outputBufferLength); 5077b0daf5cSbeveloper int temp = frames_for_duration(framerate, mixerBufferLength); 5087b0daf5cSbeveloper fMixBufferFrameCount = ((temp / frames) + 1) * frames; 5097b0daf5cSbeveloper 510a2ca4723Sbeveloper TRACE(" inputBufferLength %10Ld\n", inputBufferLength); 511a2ca4723Sbeveloper TRACE(" outputBufferLength %10Ld\n", outputBufferLength); 512a2ca4723Sbeveloper TRACE(" mixerBufferLength %10Ld\n", mixerBufferLength); 513a2ca4723Sbeveloper TRACE(" fMixBufferFrameCount %10ld\n", fMixBufferFrameCount); 5147b0daf5cSbeveloper 5158d28117fSbeveloper ASSERT((fMixBufferFrameCount % frames) == 0); 5168d28117fSbeveloper 5172e9d6607Sbeveloper if (fMixBuffer) 5182e9d6607Sbeveloper rtm_free(fMixBuffer); 519356855c3Sbeveloper if (fRtmPool) 520356855c3Sbeveloper rtm_delete_pool(fRtmPool); 5217b0daf5cSbeveloper int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount; 522356855c3Sbeveloper if (B_OK != rtm_create_pool(&fRtmPool, size)) 523356855c3Sbeveloper fRtmPool = 0; 524356855c3Sbeveloper fMixBuffer = (float *)rtm_alloc(fRtmPool, size); 5257b0daf5cSbeveloper ASSERT(fMixBuffer); 5267b0daf5cSbeveloper 5277b0daf5cSbeveloper memset(fMixBuffer, 0, size); 5282e9d6607Sbeveloper 5292e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 5307b0daf5cSbeveloper fInputChannelInfo[i].buffer_base = &fMixBuffer[i]; 531d5848e21Sbeveloper 5329c3be6a5Sbeveloper UpdateInputChannelDestinationMask(); 5339c3be6a5Sbeveloper UpdateInputChannelDestinations(); 5342e9d6607Sbeveloper } 535