Skip to content

Add two-input stereo-output microphone mode#3757

Open
seanogdelaney wants to merge 2 commits into
jamulussoftware:mainfrom
seanogdelaney:two-in-stereo-out-mic
Open

Add two-input stereo-output microphone mode#3757
seanogdelaney wants to merge 2 commits into
jamulussoftware:mainfrom
seanogdelaney:two-in-stereo-out-mic

Conversation

@seanogdelaney

Copy link
Copy Markdown

Summary:

Validation:

  • Compiles on Linux
  • Runs on Linux
  • Two channels appear in mixer as expected, with second suffixed 'Mic', using vocal icon.

Notes:
Running two jamulus clients can achieve this, but is a bit awkward.
This way makes it more accessible (less flexible, but easier).

@ann0see ann0see requested review from dingodoppelt and pljones June 28, 2026 20:47
@dingodoppelt

Copy link
Copy Markdown
Member

From a first skim through the code I could gather that CAuxiliaryMonoSender basically duplicates CClient without raw audio transmission. Is there a reason for not trying to reuse CClient?
I guess since it is client only code we now occupy two channels with one client?
Have you thought about less invasive alternatives like UI only changes, i.e. splitting stereo clients (with vocal and instrument combination) into separate channels?

@seanogdelaney

seanogdelaney commented Jun 28, 2026 via email

Copy link
Copy Markdown
Author

@dingodoppelt

dingodoppelt commented Jun 29, 2026

Copy link
Copy Markdown
Member

I think you may misunderstand. A UI-only change won't work here. Each client channel exists on the server, where it is mixed and sent to each clients. To expose separate vocal and instrument faders, the server must receive them as separate channels. Otherwise we'd need to modify the server to split the incoming stereo stream into separate mono channels when this client mode is enabled, which would be a considerably more invasive change.

I find this change very invasive by it's sheer size while it is not very clear what is to be achieved.
If we are using two server slots, why is this mono-only/non-raw? A client already sends two mono signals in all available audio qualities. This should be exploited first before duplication of code.
Why do you think changes to the server would be more invasive? A server would receive a stereo packet and treat it like two mono paths. I'd start from there to keep changes simple and small.

@seanogdelaney

Copy link
Copy Markdown
Author

Firstly, respect (to you and the community) for such fast responses on issues / PRs. It's much appreciated!

You express three very reasonable concerns: intent clarity, code size, and the server-side alternative. My perspective is:

Intent Clarity: The aim is "mixer shows 1 fader per source" instead of "1 fader per person". The most common situation is a person who sings and plays an instrument (two sources). This PR addresses that case, but could be extended later (e.g. stereo instrument + mic), see for example issue #96.

Code size: This change is about 300 real lines of code, mostly isolated in the auxiliary sender. If it can be achieved in less code (without sacrificing quality / maintainability), I'd like that very much.

Server-side alternative: I agree it's possible (i.e. a client check-box triggers the server to split a stereo channel into two mono channels before the mixer stage). It's not clear to me that this would be less code, or less invasive. It also doesn't provide a natural path to cases "stereo DJ decks + mic", or the more general multichannel support discussed in #96.

So my thinking was to implement the more general model from the outset: independently mixable sources are sent as independent channels. This PR just implements the simplest two-source case.

@dingodoppelt

Copy link
Copy Markdown
Member

This way makes it more accessible (less flexible, but easier).

Is there really a usecase for this? Why is this better than using two clients or simply mixing a stereo mix and feeding that into Jamulus for the sake of stereo and raw audio? I don't know if people will use this when there is not even a stereo signal available.
By the approach taken a lot of code is duplicated and would have to be maintained in parallel. I really think the server is the place to start here and have clients do the visuals.
I could see some benefit in this, if...

  • There was only one channel occupied at the server
  • There was stereo
  • There was raw audio

In general I think we shouldn't give two channels to one client. I know this is being done but I have never liked it and I still think people shouldn't do it.
Missing stereo and raw audio support will be a deal breaker for many.

@seanogdelaney

Copy link
Copy Markdown
Author

Thanks, that helps clarify the concern.

Use case: I believe there is a real use case here. A mono instrument plus mono vocal is common for people playing in Jamulus “rock band” style sessions: bass + vocal, guitar + vocal, etc. In that situation, independent mixer faders are useful even though neither source needs stereo.

Why not two Jamulus clients: that is what I currently do, but it is hard to recommend to less technical users. It requires either scripts with separate ini files, or repeated manual configuration. Many users will find that awkward or conceptually confusing.

Code duplication: I agree this is the main weakness of the current implementation. If you are open to it, I can reduce this by factoring the relevant sender-side parts out of CClient rather than maintaining parallel code.

Stereo / raw audio: agreed, this PR does not cover those cases. They would require more code, so I would prefer to handle them in a follow-up PR if this general direction is acceptable.

Multiple mixer channels per user: I understand this is the central design disagreement. I do not want to argue against the maintainers’ preferred model. My motivation is simply that I believe many users would find this useful, myself included, and that independently mixable sources mapping to independent channels is a natural model for this use case.

@dingodoppelt

Copy link
Copy Markdown
Member

Thanks, that helps clarify the concern.

Use case: I believe there is a real use case here. A mono instrument plus mono vocal is common for people playing in Jamulus “rock band” style sessions: bass + vocal, guitar + vocal, etc. In that situation, independent mixer faders are useful even though neither source needs stereo.

I use a similar setup (multiple instruments, analog and digital through some effect chains) and I surely need stereo for everything. I'm mixing all my channels locally and just send a stereo mix.

Why not two Jamulus clients: that is what I currently do, but it is hard to recommend to less technical users. It requires either scripts with separate ini files, or repeated manual configuration. Many users will find that awkward or conceptually confusing.

To launch the client with a separate INI file you don't need a script, just the cli option -i. This is well documented and not at all awkward or confusing in my opinion. At least on Linux this is a one-click matter.

Code duplication: I agree this is the main weakness of the current implementation. If you are open to it, I can reduce this by factoring the relevant sender-side parts out of CClient rather than maintaining parallel code.

I'd say CServer is a better place to make this happen as we already have a path to send two mono channels (stereo configuration)

Multiple mixer channels per user: I understand this is the central design disagreement. I do not want to argue against the maintainers’ preferred model. My motivation is simply that I believe many users would find this useful, myself included, and that independently mixable sources mapping to independent channels is a natural model for this use case.

"Multiple" is not what you actually propose here. It is "two mono signals" which is a stereo signal in current Jamulus terms. This only applies to users using mono for all their instruments exclusively. This may be ok for a bass player but pianists, guitarists and vocalists generally use stereo signals for the sake of sound fidelity (this is what we tell users when they join a server with mono signals) and those users wouldn't make use of this feature.

@dingodoppelt

Copy link
Copy Markdown
Member

We have #3746 that introduces multichannel support but only on iOS.
If we had this cross platform we could think about acquiring more than two channels and send those simultaneously from one client. Either in multiple messages or over dedicated sockets.
Since the limitation mono/compressed is not a technical boundary but a deliberate design decision and tailored to a very limited use case I don't think this is the right approach. Not many users will make use of this I fear.

@dingodoppelt

dingodoppelt commented Jun 29, 2026

Copy link
Copy Markdown
Member

If running two clients seems awkward you may want to try running the secondary client without a GUI (-n) so you don't receive chat messages twice and stuff like that. An RPC method has just been introduced to mute yourself or you could use MIDI to control the headless client.
In theory you could have even more clients with stereo/raw sound that way.

@dingodoppelt

Copy link
Copy Markdown
Member

#1063 and #1840 are still open and it hasn't been agreed upon a strategy to pursue with this but the ideas seem to point in a different direction of a more general way of sending multichannel audio. Use cases differ wildly and we need the widest possible coverage.

Comment thread src/client.cpp

bool CClient::CanUseAuxiliaryMonoSender()
{
return ( eAudioQuality != AQ_RAW ) && ( Sound.GetNumInputChannels() >= 2 ) && ( Sound.GetLeftInputChannel() >= 0 ) &&

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is raw audio transmission left out?

Comment thread src/util.h
CC_MONO_IN_STEREO_OUT = 1,
CC_STEREO = 2
CC_STEREO = 2,
CC_TWO_IN_STEREO_OUT = 3

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say stereo already covers this. This should rather tell the server to treat a stereo signal as two mono signals and have the client display two channels instead of one.

Comment thread src/client.cpp
}
}

void Process ( const CVector<int16_t>& vecMonoSamples, const bool bMute )

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would have to be maintained separately from the main code for audio transmission and is already out of date as it doesn't support raw audio or even stereo while there is no clear reason other than covering a singular use case.
While we have a socket, why not use it to its full potential?

Comment thread src/client.cpp
&vecCodedData[0],
iCodedBytes );
Channel.PrepAndSendPacket ( &Socket, vecCodedData, iCodedBytes );
Channel.GetData ( vecReceiveData, iCodedBytes );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server sends audio that will never be played back from the client. Is this really necessary? Shouldn't the server rather not return anything, just consume additional samples from the client? CAuxiliaryMonoSender doesn't imply receiving as well.

@pljones

pljones commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

A another user on a server, I have no idea other than each fader is a real person. I want to see what each fader represents (i.e. if someone is a singer and sitting next to them is a guitar player, I want both their names and instruments). So, effectively, I see no model - from other Jamulus users' perspectives - where a fader should not reflect the profile information as well as the audio channel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants