1678c2017Sbeveloper #include <MediaNode.h> 22e9d6607Sbeveloper #include <Buffer.h> 32e9d6607Sbeveloper #include <RealtimeAlloc.h> 4678c2017Sbeveloper #include "MixerInput.h" 5678c2017Sbeveloper #include "MixerCore.h" 6e6c7c99fSbeveloper #include "MixerUtils.h" 7*88777023Sbeveloper #include "ByteSwap.h" 8e6c7c99fSbeveloper #include "debug.h" 9678c2017Sbeveloper 102e9d6607Sbeveloper MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampleRate, int32 mixFramesCount, bigtime_t mixStartTime) 11e6c7c99fSbeveloper : fCore(core), 122e9d6607Sbeveloper fInput(input), 13*88777023Sbeveloper fInputByteSwap(0), 142e9d6607Sbeveloper fInputChannelInfo(0), 152e9d6607Sbeveloper fInputChannelCount(0), 162e9d6607Sbeveloper fInputChannelMask(0), 172e9d6607Sbeveloper fMixerChannelInfo(0), 182e9d6607Sbeveloper fMixerChannelCount(0), 192e9d6607Sbeveloper fMixBuffer(0), 202e9d6607Sbeveloper fMixBufferSampleRate(0), 212e9d6607Sbeveloper fMixBufferFrames(0), 222e9d6607Sbeveloper fMixBufferStartTime(0), 232e9d6607Sbeveloper fUserOverridesChannelDesignations(false) 24678c2017Sbeveloper { 25e6c7c99fSbeveloper fix_multiaudio_format(&fInput.format.u.raw_audio); 26e6c7c99fSbeveloper PRINT_INPUT("MixerInput::MixerInput", fInput); 27e6c7c99fSbeveloper PRINT_CHANNEL_MASK(fInput.format); 282e9d6607Sbeveloper 292e9d6607Sbeveloper ASSERT(fInput.format.u.raw_audio.channel_count > 0); 302e9d6607Sbeveloper 312e9d6607Sbeveloper fInputChannelCount = fInput.format.u.raw_audio.channel_count; 322e9d6607Sbeveloper fInputChannelMask = fInput.format.u.raw_audio.channel_mask; 332e9d6607Sbeveloper fInputChannelInfo = new input_chan_info[fInputChannelCount]; 342e9d6607Sbeveloper 35*88777023Sbeveloper // perhaps we need byte swapping 36*88777023Sbeveloper if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) { 37*88777023Sbeveloper if ( fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT 38*88777023Sbeveloper || fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT 39*88777023Sbeveloper || fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) { 40*88777023Sbeveloper fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format); 41*88777023Sbeveloper } 42*88777023Sbeveloper } 43*88777023Sbeveloper 442e9d6607Sbeveloper // initialize fInputChannelInfo 452e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) { 462e9d6607Sbeveloper fInputChannelInfo[i].buffer_base = 0; // will be set by SetMixBufferFormat() 472e9d6607Sbeveloper fInputChannelInfo[i].designations = 0; // will be set by UpdateChannelDesignations() 482e9d6607Sbeveloper fInputChannelInfo[i].gain = 1.0; 492e9d6607Sbeveloper } 502e9d6607Sbeveloper 512e9d6607Sbeveloper // fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateMixerChannels() 522e9d6607Sbeveloper 532e9d6607Sbeveloper SetMixBufferFormat(mixSampleRate, mixFramesCount, mixStartTime); 542e9d6607Sbeveloper UpdateChannelDesignations(); 552e9d6607Sbeveloper UpdateMixerChannels(); 562e9d6607Sbeveloper 572e9d6607Sbeveloper 582e9d6607Sbeveloper // XXX a test: 592e9d6607Sbeveloper SetMixerChannelGain(0, 0.222); 602e9d6607Sbeveloper SetMixerChannelGain(1, 0.444); 612e9d6607Sbeveloper AddInputChannelDesignation(0, B_CHANNEL_REARRIGHT); 622e9d6607Sbeveloper SetMixerChannelGain(2, 0.666); 632e9d6607Sbeveloper AddInputChannelDesignation(1, B_CHANNEL_REARLEFT); 64678c2017Sbeveloper } 65678c2017Sbeveloper 66678c2017Sbeveloper MixerInput::~MixerInput() 67678c2017Sbeveloper { 682e9d6607Sbeveloper if (fMixBuffer) 692e9d6607Sbeveloper rtm_free(fMixBuffer); 702e9d6607Sbeveloper delete [] fInputChannelInfo; 712e9d6607Sbeveloper delete [] fMixerChannelInfo; 72678c2017Sbeveloper } 73678c2017Sbeveloper 74678c2017Sbeveloper void 75678c2017Sbeveloper MixerInput::BufferReceived(BBuffer *buffer) 76678c2017Sbeveloper { 77*88777023Sbeveloper void *data; 78*88777023Sbeveloper size_t size; 79*88777023Sbeveloper bigtime_t start; 80*88777023Sbeveloper 812e9d6607Sbeveloper ASSERT(fMixBuffer); 822e9d6607Sbeveloper 83*88777023Sbeveloper data = buffer->Data(); 84*88777023Sbeveloper size = buffer->SizeUsed(); 85*88777023Sbeveloper start = buffer->Header()->start_time; 86*88777023Sbeveloper 87*88777023Sbeveloper // swap the byte order of this buffer, if necessary 88*88777023Sbeveloper if (fInputByteSwap) 89*88777023Sbeveloper fInputByteSwap->Swap(data, size); 90*88777023Sbeveloper 91*88777023Sbeveloper 92*88777023Sbeveloper printf("mix buffer start %14Ld, buffer start %14Ld\n", fMixBufferStartTime, start); 93678c2017Sbeveloper } 947ee2c804Sbeveloper 957ee2c804Sbeveloper media_input & 967ee2c804Sbeveloper MixerInput::MediaInput() 977ee2c804Sbeveloper { 987ee2c804Sbeveloper return fInput; 997ee2c804Sbeveloper } 100e6c7c99fSbeveloper 101e6c7c99fSbeveloper int32 102e6c7c99fSbeveloper MixerInput::ID() 103e6c7c99fSbeveloper { 104e6c7c99fSbeveloper return fInput.destination.id; 105e6c7c99fSbeveloper } 106e6c7c99fSbeveloper 1072e9d6607Sbeveloper void 1082e9d6607Sbeveloper MixerInput::AddInputChannelDesignation(int channel, uint32 des) 1092e9d6607Sbeveloper { 1102e9d6607Sbeveloper ASSERT(count_nonzero_bits(des) == 1); 111e6c7c99fSbeveloper 1122e9d6607Sbeveloper // test if the channel is valid 1132e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 1142e9d6607Sbeveloper return; 1152e9d6607Sbeveloper 1162e9d6607Sbeveloper // test if it is already set 1172e9d6607Sbeveloper if (fInputChannelInfo[channel].designations & des) 1182e9d6607Sbeveloper return; 1192e9d6607Sbeveloper 1202e9d6607Sbeveloper // remove it from all other channels that might have it 1212e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 1222e9d6607Sbeveloper fInputChannelInfo[i].designations &= ~des; 1232e9d6607Sbeveloper 1242e9d6607Sbeveloper // add it to specified channel 1252e9d6607Sbeveloper fInputChannelInfo[channel].designations |= des; 1262e9d6607Sbeveloper 1272e9d6607Sbeveloper fUserOverridesChannelDesignations = true; 1282e9d6607Sbeveloper UpdateMixerChannels(); 1292e9d6607Sbeveloper } 1302e9d6607Sbeveloper 1312e9d6607Sbeveloper void 1322e9d6607Sbeveloper MixerInput::RemoveInputChannelDesignation(int channel, uint32 des) 1332e9d6607Sbeveloper { 1342e9d6607Sbeveloper ASSERT(count_nonzero_bits(des) == 1); 1352e9d6607Sbeveloper 1362e9d6607Sbeveloper // test if the channel is valid 1372e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 1382e9d6607Sbeveloper return; 1392e9d6607Sbeveloper 1402e9d6607Sbeveloper // test if it is really set 1412e9d6607Sbeveloper if ((fInputChannelInfo[channel].designations & des) == 0) 1422e9d6607Sbeveloper return; 1432e9d6607Sbeveloper 1442e9d6607Sbeveloper // remove it from specified channel 1452e9d6607Sbeveloper fInputChannelInfo[channel].designations &= ~des; 1462e9d6607Sbeveloper 1472e9d6607Sbeveloper fUserOverridesChannelDesignations = true; 1482e9d6607Sbeveloper UpdateMixerChannels(); 1492e9d6607Sbeveloper } 1502e9d6607Sbeveloper 1512e9d6607Sbeveloper uint32 1522e9d6607Sbeveloper MixerInput::GetInputChannelDesignations(int channel) 1532e9d6607Sbeveloper { 1542e9d6607Sbeveloper // test if the channel is valid 1552e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 1562e9d6607Sbeveloper return 0; 1572e9d6607Sbeveloper return fInputChannelInfo[channel].designations; 1582e9d6607Sbeveloper } 1592e9d6607Sbeveloper 1602e9d6607Sbeveloper uint32 1612e9d6607Sbeveloper MixerInput::GetInputChannelType(int channel) 1622e9d6607Sbeveloper { 1632e9d6607Sbeveloper // test if the channel is valid 1642e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 1652e9d6607Sbeveloper return 0; 1662e9d6607Sbeveloper return GetChannelMask(channel, fInputChannelMask); 1672e9d6607Sbeveloper } 1682e9d6607Sbeveloper 1692e9d6607Sbeveloper void 1702e9d6607Sbeveloper MixerInput::SetInputChannelGain(int channel, float gain) 1712e9d6607Sbeveloper { 1722e9d6607Sbeveloper // test if the channel is valid 1732e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 1742e9d6607Sbeveloper return; 1752e9d6607Sbeveloper if (gain < 0.0f) 1762e9d6607Sbeveloper gain = 0.0f; 1772e9d6607Sbeveloper 1782e9d6607Sbeveloper fInputChannelInfo[channel].gain = gain; 1792e9d6607Sbeveloper } 1802e9d6607Sbeveloper 1812e9d6607Sbeveloper float 1822e9d6607Sbeveloper MixerInput::GetInputChannelGain(int channel) 1832e9d6607Sbeveloper { 1842e9d6607Sbeveloper // test if the channel is valid 1852e9d6607Sbeveloper if (channel < 0 || channel >= fInputChannelCount) 1862e9d6607Sbeveloper return 0.0f; 1872e9d6607Sbeveloper return fInputChannelInfo[channel].gain; 1882e9d6607Sbeveloper } 1892e9d6607Sbeveloper 1902e9d6607Sbeveloper void 1912e9d6607Sbeveloper MixerInput::UpdateChannelDesignations() 1922e9d6607Sbeveloper { 1932e9d6607Sbeveloper // is the user already messed with the assignmens, don't do anything. 1942e9d6607Sbeveloper if (fUserOverridesChannelDesignations) 1952e9d6607Sbeveloper return; 1962e9d6607Sbeveloper 1972e9d6607Sbeveloper printf("UpdateChannelDesignations: enter\n"); 1982e9d6607Sbeveloper 1992e9d6607Sbeveloper if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { 2002e9d6607Sbeveloper // a left or right channel get's output as stereo on both 2012e9d6607Sbeveloper fInputChannelInfo[0].designations = B_CHANNEL_LEFT | B_CHANNEL_RIGHT; 2022e9d6607Sbeveloper } else { 2032e9d6607Sbeveloper // everything else get's mapped 1:1 2042e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 2052e9d6607Sbeveloper fInputChannelInfo[i].designations = GetChannelMask(i, fInputChannelMask); 2062e9d6607Sbeveloper } 2072e9d6607Sbeveloper 2082e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 2092e9d6607Sbeveloper printf("UpdateChannelDesignations: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); 2102e9d6607Sbeveloper 2112e9d6607Sbeveloper printf("UpdateChannelDesignations: enter\n"); 2122e9d6607Sbeveloper } 2132e9d6607Sbeveloper 2142e9d6607Sbeveloper void 2152e9d6607Sbeveloper MixerInput::UpdateMixerChannels() 2162e9d6607Sbeveloper { 2172e9d6607Sbeveloper uint32 channel_count; 2182e9d6607Sbeveloper uint32 all_bits; 2192e9d6607Sbeveloper uint32 mask; 2202e9d6607Sbeveloper 2212e9d6607Sbeveloper mixer_chan_info *old_mixer_channel_info; 2222e9d6607Sbeveloper uint32 old_mixer_channel_count; 2232e9d6607Sbeveloper 2242e9d6607Sbeveloper ASSERT(fMixBuffer); 2252e9d6607Sbeveloper 2262e9d6607Sbeveloper printf("UpdateMixerChannels: enter\n"); 2272e9d6607Sbeveloper 2282e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 2292e9d6607Sbeveloper printf("UpdateMixerChannels: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); 2302e9d6607Sbeveloper 2312e9d6607Sbeveloper all_bits = 0; 2322e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 2332e9d6607Sbeveloper all_bits |= fInputChannelInfo[i].designations; 2342e9d6607Sbeveloper 2352e9d6607Sbeveloper printf("UpdateMixerChannels: all_bits = %08x\n", all_bits); 2362e9d6607Sbeveloper 2372e9d6607Sbeveloper channel_count = count_nonzero_bits(all_bits); 2382e9d6607Sbeveloper 2392e9d6607Sbeveloper printf("UpdateMixerChannels: %ld input channels, %ld mixer channels (%ld old)\n", fInputChannelCount, channel_count, fMixerChannelCount); 2402e9d6607Sbeveloper 2412e9d6607Sbeveloper // If we resize the channel info array, we preserve the gain setting 2422e9d6607Sbeveloper // by saving the old array until new assignments are finished, and 2432e9d6607Sbeveloper // then applying the old gains. New gains are set to 1.0 2442e9d6607Sbeveloper if (channel_count != fMixerChannelCount) { 2452e9d6607Sbeveloper old_mixer_channel_info = fMixerChannelInfo; 2462e9d6607Sbeveloper old_mixer_channel_count = fMixerChannelCount; 2472e9d6607Sbeveloper fMixerChannelInfo = new mixer_chan_info[channel_count]; 2482e9d6607Sbeveloper fMixerChannelCount = channel_count; 2492e9d6607Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) 2502e9d6607Sbeveloper fMixerChannelInfo[i].gain = 1.0; 2512e9d6607Sbeveloper } else { 2522e9d6607Sbeveloper old_mixer_channel_info = 0; 2532e9d6607Sbeveloper old_mixer_channel_count = 0; 2542e9d6607Sbeveloper } 2552e9d6607Sbeveloper 2562e9d6607Sbeveloper // assign each mixer channel one type 2572e9d6607Sbeveloper for (int i = 0, mask = 1; i < fMixerChannelCount; i++) { 2582e9d6607Sbeveloper while (mask != 0 && (all_bits & mask) == 0) 2592e9d6607Sbeveloper mask <<= 1; 260a4b8db85Sbeveloper fMixerChannelInfo[i].type = ChannelMaskToChannelType(mask); 2612e9d6607Sbeveloper mask <<= 1; 2622e9d6607Sbeveloper } 2632e9d6607Sbeveloper 2642e9d6607Sbeveloper // assign buffer_base pointer for each mixer channel 2652e9d6607Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) { 2662e9d6607Sbeveloper int j; 2672e9d6607Sbeveloper for (j = 0; j < fInputChannelCount; j++) { 268a4b8db85Sbeveloper if (fInputChannelInfo[j].designations & ChannelTypeToChannelMask(fMixerChannelInfo[i].type)) { 2692e9d6607Sbeveloper fMixerChannelInfo[i].buffer_base = &fMixBuffer[j]; 2702e9d6607Sbeveloper break; 2712e9d6607Sbeveloper } 2722e9d6607Sbeveloper } 2732e9d6607Sbeveloper if (j == fInputChannelCount) { 2742e9d6607Sbeveloper printf("buffer assignment failed for mixer chan %d\n", i); 2752e9d6607Sbeveloper fMixerChannelInfo[i].buffer_base = fMixBuffer; 2762e9d6607Sbeveloper } 2772e9d6607Sbeveloper } 2782e9d6607Sbeveloper 2792e9d6607Sbeveloper // apply old gains, overriding the 1.0 defaults for the old channels 2802e9d6607Sbeveloper if (old_mixer_channel_info != 0) { 2812e9d6607Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) { 2822e9d6607Sbeveloper for (int j = 0; j < old_mixer_channel_count; j++) { 283a4b8db85Sbeveloper if (fMixerChannelInfo[i].type == old_mixer_channel_info[j].type) { 2842e9d6607Sbeveloper fMixerChannelInfo[i].gain = old_mixer_channel_info[j].gain; 2852e9d6607Sbeveloper break; 2862e9d6607Sbeveloper } 2872e9d6607Sbeveloper } 2882e9d6607Sbeveloper } 2892e9d6607Sbeveloper // also delete the old info array 2902e9d6607Sbeveloper delete [] old_mixer_channel_info; 2912e9d6607Sbeveloper } 2922e9d6607Sbeveloper 2932e9d6607Sbeveloper for (int i = 0; i < fMixerChannelCount; i++) 294a4b8db85Sbeveloper printf("UpdateMixerChannels: mixer channel %d, type %2d, des 0x%08X, base %p, gain %.3f\n", i, fMixerChannelInfo[i].type, ChannelTypeToChannelMask(fMixerChannelInfo[i].type), fMixerChannelInfo[i].buffer_base, fMixerChannelInfo[i].gain); 2952e9d6607Sbeveloper 2962e9d6607Sbeveloper printf("UpdateMixerChannels: leave\n"); 2972e9d6607Sbeveloper } 2982e9d6607Sbeveloper 2992e9d6607Sbeveloper uint32 3002e9d6607Sbeveloper MixerInput::GetMixerChannelCount() 3012e9d6607Sbeveloper { 3022e9d6607Sbeveloper return fMixerChannelCount; 3032e9d6607Sbeveloper } 3042e9d6607Sbeveloper 3052e9d6607Sbeveloper void 306a4b8db85Sbeveloper MixerInput::GetMixerChannelInfo(int channel, const float **buffer, uint32 *sample_offset, int *type, float *gain) 3072e9d6607Sbeveloper { 3082e9d6607Sbeveloper ASSERT(fMixBuffer); 3092e9d6607Sbeveloper ASSERT(channel >= 0 && channel < fMixerChannelCount); 3102e9d6607Sbeveloper *buffer = fMixerChannelInfo[channel].buffer_base; 3112e9d6607Sbeveloper *sample_offset = sizeof(float) * fInputChannelCount; 312a4b8db85Sbeveloper *type = fMixerChannelInfo[channel].type; 3132e9d6607Sbeveloper *gain = fMixerChannelInfo[channel].gain; 3142e9d6607Sbeveloper } 3152e9d6607Sbeveloper 3162e9d6607Sbeveloper void 3172e9d6607Sbeveloper MixerInput::SetMixerChannelGain(int channel, float gain) 3182e9d6607Sbeveloper { 3192e9d6607Sbeveloper if (channel < 0 || channel >= fMixerChannelCount) 3202e9d6607Sbeveloper return; 3212e9d6607Sbeveloper if (gain < 0.0f) 3222e9d6607Sbeveloper gain = 0.0f; 3232e9d6607Sbeveloper fMixerChannelInfo[channel].gain = gain; 3242e9d6607Sbeveloper } 3252e9d6607Sbeveloper 3262e9d6607Sbeveloper float 3272e9d6607Sbeveloper MixerInput::GetMixerChannelGain(int channel) 3282e9d6607Sbeveloper { 3292e9d6607Sbeveloper if (channel < 0 || channel >= fMixerChannelCount) 3302e9d6607Sbeveloper return 1.0; 3312e9d6607Sbeveloper return fMixerChannelInfo[channel].gain; 3322e9d6607Sbeveloper } 3332e9d6607Sbeveloper 3342e9d6607Sbeveloper void 3352e9d6607Sbeveloper MixerInput::SetMixBufferFormat(float samplerate, int32 frames, bigtime_t starttime) 3362e9d6607Sbeveloper { 3372e9d6607Sbeveloper fMixBufferSampleRate = samplerate; 3382e9d6607Sbeveloper fMixBufferFrames = frames; 3392e9d6607Sbeveloper fMixBufferStartTime = starttime; 3402e9d6607Sbeveloper 3412e9d6607Sbeveloper if (fMixBuffer) 3422e9d6607Sbeveloper rtm_free(fMixBuffer); 3432e9d6607Sbeveloper fMixBuffer = (float *)rtm_alloc(NULL, sizeof(float) * fInputChannelCount * fMixBufferFrames); 3442e9d6607Sbeveloper 3452e9d6607Sbeveloper for (int i = 0; i < fInputChannelCount; i++) 3462e9d6607Sbeveloper fInputChannelInfo[i].buffer_base = &fMixBuffer[i * fMixBufferFrames]; 3472e9d6607Sbeveloper } 348