Implementing 1 input, 2 outputs (i.e. mono -> stereo)

Hi everyone.

I’d like to know how to get your IPlugEffect to give you the “mono → stereo” option when you add it to your host’s channel strip. In other words, to have the possibility to have 1 input and 2 outputs.

I tried adding “1-2” in the channels IO configuration, but apparently that is not enough:

#define PLUG_CHANNEL_IO “1-1 1-2 2-2”

I only tried the above out of intuition, but I don’t know if that is even correct or if I am missing something else.

Thanks,

Ric

What host/format are you testing?

I am building an AUv2 for Logic. I start by duplicating the IPlugEffect.

I am not sure if this is some kind of regression in Logic, auval output seems correct

beast-3:~ oli$ auval -v aufx Ipef Acme

    AU Validation Tool
    Version: 1.6.1a1
    Copyright 2003-2013, Apple Inc. All Rights Reserved.
    Specify -h (-help) for command options

--------------------------------------------------
VALIDATING AUDIO UNIT: 'aufx' - 'Ipef' - 'Acme'
--------------------------------------------------
Manufacturer String: AcmeInc
AudioUnit Name: IPlugEffect
Component Version: 1.0.0 (0x10000)

* * PASS
--------------------------------------------------
TESTING OPEN TIMES:
COLD:
BEGIN IPLUG CHANNEL IO PARSER --------------------------------------------------
Channel I/O #1 - 1-1
               - input bus count: 1, output bus count 1
               - channel count on input bus 1: 1
               - channel count on output bus 1: 1
               - input channel count across all buses: 1, output channel count across all buses 1

Channel I/O #2 - 1-2
               - input bus count: 1, output bus count 1
               - channel count on input bus 1: 1
               - channel count on output bus 1: 2
               - input channel count across all buses: 1, output channel count across all buses 2

Channel I/O #3 - 2-2
               - input bus count: 1, output bus count 1
               - channel count on input bus 1: 2
               - channel count on output bus 1: 2
               - input channel count across all buses: 2, output channel count across all buses 2

3 I/O configs detected
Total # in chans: 2, Total # out chans: 2

END IPLUG CHANNEL IO PARSER --------------------------------------------------
Time to open AudioUnit:         4.862 ms
WARM:
BEGIN IPLUG CHANNEL IO PARSER --------------------------------------------------
Channel I/O #1 - 1-1
               - input bus count: 1, output bus count 1
               - channel count on input bus 1: 1
               - channel count on output bus 1: 1
               - input channel count across all buses: 1, output channel count across all buses 1

Channel I/O #2 - 1-2
               - input bus count: 1, output bus count 1
               - channel count on input bus 1: 1
               - channel count on output bus 1: 2
               - input channel count across all buses: 1, output channel count across all buses 2

Channel I/O #3 - 2-2
               - input bus count: 1, output bus count 1
               - channel count on input bus 1: 2
               - channel count on output bus 1: 2
               - input channel count across all buses: 2, output channel count across all buses 2

3 I/O configs detected
Total # in chans: 2, Total # out chans: 2

END IPLUG CHANNEL IO PARSER --------------------------------------------------
Time to open AudioUnit:         0.074  ms
FIRST TIME:
Time for initialization:        2.479 ms

* * PASS
--------------------------------------------------
VERIFYING DEFAULT SCOPE FORMATS:
Input Scope Bus Configuration:
 Default Bus Count:1
    Bus Name: Input
    Default Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
    Has Channel Layouts: 0x640001 0x650002

Output Scope Bus Configuration:
 Default Bus Count:1
    Bus Name: Output
    Default Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
    Has Channel Layouts: 0x640001 0x650002

* * PASS
--------------------------------------------------
VERIFYING REQUIRED PROPERTIES:

* * PASS
--------------------------------------------------
VERIFYING RECOMMENDED PROPERTIES:
  VERIFYING PROPERTY: Latency
    PASS
  VERIFYING PROPERTY: Tail Time
    PASS
  VERIFYING PROPERTY: Bypass Effect
    PASS

* * PASS
--------------------------------------------------
VERIFYING OPTIONAL PROPERTIES:

* * PASS
--------------------------------------------------
VERIFYING SPECIAL PROPERTIES:

VERIFYING CUSTOM UI
Cocoa Views Available: 1
  IPlugEffect_View
    PASS

DEFAULT PRESET: 0, Name:

HAS FACTORY PRESETS

VERIFYING CLASS INFO
WARNING: Preset name is not retained in retrieved class data
    PASS

TESTING HOST CALLBACKS
    PASS

* * PASS
--------------------------------------------------
PUBLISHED PARAMETER INFO:

# # # 1 Global Scope Parameters:
Parameter ID:0
Name: Gain
Parameter Type: %
Values: Minimum = 0.000000, Default = 0.000000, Maximum = 100.000000
Flags: High Resolution, Readable, Writable
  -parameter PASS

Testing that parameters retain value across reset and initialization
  PASS

* * PASS
--------------------------------------------------
FORMAT TESTS:

Reported Channel Capabilities (explicit):
      [1, 1]  [1, 2]  [2, 2]

Input/Output Channel Handling:
1-1   1-2   1-4   1-5   1-6   1-7   1-8   2-2   2-4   2-5   2-6   2-7   2-8   4-4   4-5   5-5   6-6   7-7   8-8
X     X                                   X

# # AudioChannelLayouts (2), Input Scope:
ChannelLayout is Writable: F
The Unit publishes the following Channel Layouts:
  0x640001, 0x650002,

Is Audio Channel Layout Available:
Mono    Stereo  Binau.  AU_4    Ambi.   AU_5    AU_5_0  AU_6    AU_6_0  AU_7_0  AU_7_0F AU_8    AU_5_1  AU_6_1  AU_7_1  AU_7_1F
X       X

# # AudioChannelLayouts (2), Output Scope:
ChannelLayout is Writable: F
The Unit publishes the following Channel Layouts:
  0x640001, 0x650002,

Is Audio Channel Layout Available:
Mono    Stereo  Binau.  AU_4    Ambi.   AU_5    AU_5_0  AU_6    AU_6_0  AU_7_0  AU_7_0F AU_8    AU_5_1  AU_6_1  AU_7_1  AU_7_1F
X       X

* * PASS
--------------------------------------------------
RENDER TESTS:

Input Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
Output Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
Render Test at 512 frames
Slicing Render Test at 64 frames
  PASS


Render Test at 64 frames, sample rate: 22050 Hz
Render Test at 137 frames, sample rate: 96000 Hz
Render Test at 4096 frames, sample rate: 48000 Hz
Render Test at 4096 frames, sample rate: 192000 Hz
Render Test at 4096 frames, sample rate: 11025 Hz
Render Test at 512 frames, sample rate: 44100 Hz
  PASS

1 Channel Test:
Render Test at 512 frames
  PASS

1 to 2 Channel Render Test at 256 frames
  PASS

Checking connection semantics:
Connection format:
AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
  PASS

Bad Max Frames - Render should fail
  PASS

Checking parameter setting
Using AudioUnitSetParameter
Using AudioUnitScheduleParameter
  PASS

Test MIDI
  PASS

* * PASS
--------------------------------------------------
AU VALIDATION SUCCEEDED.
--------------------------------------------------

thanks for the reply…

mmh, it seems fine then… the reason l posted this question is simply because Logic won’t let me insert the effect using the “mono → stereo” option as is the case with other plugins…

just to confirm, all I am supposed to do is to define this line like this?:

#define PLUG_CHANNEL_IO “1-1 1-2 2-2”

Yes its correct.

#define PLUG_CHANNEL_IO “1-1”

mono only is not working in the latest logic either.

hmm…

I see… it seems a lot of things changed with the 10.5 version but I don’t suppose they would’ve messed this up…

Anyway, I used to work in Juce beore, and setting up the channels’ IO configuration wasn’t straightforward either. You had to set it up when creating the project and you couldn’t change it after that.

totally possible. Multibus was messed up in the initial 10.5 release and me and others had to report it

now that l remember it was reported some sample libraries lost their mono option in 10.5

MonoTo Stereo:
#define PLUG_CHANNEL_IO “1-1 1-2 2-2”
works perfect (Logic10.5.1 OSX10.14.6)
but if only MonoToMono is defined:
#define PLUG_CHANNEL_IO “1-1”
crashes AU validator:

RENDER TESTS:

Input Format: AudioStreamBasicDescription: 1 ch, 44100 Hz, ‘lpcm’ (0x00000029) 32-bit little-endian float, deinterleaved
Output Format: AudioStreamBasicDescription: 1 ch, 44100 Hz, ‘lpcm’ (0x00000029) 32-bit little-endian float, deinterleaved
Render Test at 512 frames

validation result: crashed validation

and also crashes Reaper 6.15.0

I checked MonoToStereo only:
#define PLUG_CHANNEL_IO “1-2”
crashes AU validator and Reaper.

The reason that crashes is unrelated. If you don’t have 2-2 as an option, there will not be a scratch buffer for input channel 2, and this code will try to access invalid channel data.

void IPlugEffect::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
{
  const double gain = GetParam(kGain)->Value() / 100.;
  const int nChans = NOutChansConnected();
  
  for (int s = 0; s < nFrames; s++) {
    for (int c = 0; c < nChans; c++) {
      outputs[c][s] = inputs[c][s] * gain; // inputs[1][s] is invalid with PLUG_CHANNEL_IO “1-2”
    }
  }
}
1 Like

MonoTo Stereo:
#define PLUG_CHANNEL_IO “1-1 1-2 2-2”
works perfect (Logic10.5.1 OSX10.14.6)

when you say this works perfectly in Logic, does it mean it lets you insert the plugin as “mono->stereo” or simply that it doesn’t crash the validation?

Yes, Logic lets me insert the plugin as Mono->Stereo, but of course, only on Mono Channels and only if there is no Stereo plugin already on the channel.
Screenshot 2020-11-03 at 06.13.04

in my code I use:

if (NInChansConnected() > 1) { // Stereo In

and not:

NOutChansConnected();

1 Like

What version of Logic do you have @JohnCrosby ?

Ok thanks… that approach with NInChansConnected actually worked! I still used NOutChansConnected further down in order to differentiate the setups during processing.

I must say though that I have since upgraded to Catalina (against all advices) and I’ve found that Logic’s auval is way more thorough than before in terms of channel IO… so that might have made some difference as well. (so my setup is Logic 10.5.1 on Catalina 10.15.7)

Below is a Minimal plugin I made just for testing and all defined configurations work as intended:

void Minimal2::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
{
double gain = GetParam(kGain)->Value() / 100.;

// Stereo (swap L and R)
if (NInChansConnected() > 1)
{
    for (int s=0 ; s<nFrames ; ++s)
    {
        outputs[0][s] = inputs[1][s];
        outputs[1][s] = inputs[0][s];
    }
}

else
{   // Mono -> Stereo (apply gain)
    if (NOutChansConnected() > 1)
    {
        for (int s=0 ; s<nFrames ; ++s)
        {
            outputs[0][s] = inputs[0][s] * gain;
            outputs[1][s] = inputs[0][s] * gain;
        }
    }
    
    else
    {
        // Mono (apply inverse gain)
        for (int s=0 ; s<nFrames ; ++s)
        {
            outputs[0][s] = inputs[0][s] * (1.0 - gain);
        }
    }
}

}

Thank you both for all the help.

1 Like

So @Ric Mono busses are working for you now in Logic X? ! I am confused

Yes they are. In fact I have never had problems with either “mono” or “stereo” configurations, only with “mono to stereo” which is why I asked around if anyone had the same problem.

I have now created another test example with only the “mono” option, just to see if it was fine:

#define PLUG_CHANNEL_IO “1-1”

and yes it works normally.

#define PLUG_CHANNEL_IO “1-1”
works normally for me too, but only after I removed:

mMeterSender.ProcessBlock(inputs, nFrames, kCtrlTagMeter);

changing only:

IPeakSender<2> mMeterSender;

to:

IPeakSender<1> mMeterSender;

in the header file was not enough. Maybe I am doing something wrong because I can not use meters in Mono only (#define PLUG_CHANNEL_IO “1-1”) version. No big deal as I use the multi (#define PLUG_CHANNEL_IO “1-1 1-2 2-2”) version where everything works :slight_smile:

Exactly. I always define my variables assuming stereo even if then I end up using it in mono.

Often times you would just iterate over the available channels and process independently. :raised_hands: