SDP meta data and channel information

The Protocol-Driven Stage: Why SDP Changes Everything for Live Sound

For decades, the foundation of a successful live show has been the patch master—a highly skilled human who translates a band’s technical needs (their stage plot and input list) into physical cables. The Festival Patch formalized this by making the mixing console channels static, minimizing changeover time by relying on human speed and organizational charts.

But what happens when the patch list becomes part of the digital DNA of the audio system?

The demonstration of embedding specific equipment metadata—like the microphone model ($\text{SM57}$), phantom power ($\text{P48}$), and gain settings—directly into the same protocol (SDP) that defines the stream count and routing, paves the way for the Automated Stage.

The End of Changeover Chaos

In a traditional festival scenario, the greatest risk is the 15-minute changeover. Even with a standardized patch, every connection involves human decisions, risk of error, and lost time.

Integrating detailed equipment data into a standard protocol offers three revolutionary benefits:

  1. Instant Digital Patching: When a band’s touring engineer loads their show file (their mixer settings), the system wouldn’t just expect an input on Channel 3; it would receive a data stream labeled “Snare Top” with the $\text{SSRC}$ (Source ID) and an explicit metadata tag demanding the $\text{SM57}$ with $\text{P48}$ off and a specific preamp gain.

  2. Self-Correction and Verification: The stage can instantly perform a digital handshake. The physical stage box could verify, via a network query, “Is an Audix D6 connected to Kick Out? Is its phantom power off?” If the wrong mic is used, or $\text{P48}$ is mistakenly turned on (potentially damaging a ribbon mic), the system could flag the error to the patch master immediately, before the band even plays.

  3. True Plug-and-Play Touring: For the first time, a sound engineer could reliably carry a “show on a stick” that contains not just their mix, but the entire equipment specification and routing logic. As soon as the engineer’s control surface connects to the house system, the SDP-integrated metadata would automatically configure all relevant preamp settings, labeling, and signal flow, making festival sound checks obsolete for most acts.

This shift transforms the sound engineer’s role from a physical cable manager to a network systems architect. The complexity of a 64-channel festival stage doesn’t disappear, but the risk of human error and the pressure of the clock are drastically reduced, ensuring a higher quality, more consistent show for every single act.

Consider what a real session may contain

 

Ch # a=label (Console Label) Performer/Role a=track-name (DAW Slug) Mic Used P48 (Phantom Power) Gain Setting Pad Setting
01 Kick In Drummer $\text{KICK\_IN\_BETA91A}$ Beta 91A $\text{OFF}$ $\text{+10dB}$ $\text{0dB}$
02 Kick Out Drummer $\text{KICK\_OUT\_D6}$ Audix D6 $\text{OFF}$ $\text{+25dB}$ $\text{0dB}$
03 Snare Top Drummer $\text{SNARE\_TOP\_SM57}$ SM57 $\text{OFF}$ $\text{+35dB}$ $\text{0dB}$
04 Snare Bottom Drummer $\text{SNARE\_BOT\_E604}$ e604 $\text{OFF}$ $\text{+30dB}$ $\text{0dB}$
05 Hi-Hat Drummer $\text{HIHAT\_C451B}$ C451B $\text{ON}$ $\text{+40dB}$ $\text{10dB}$
06 Tom 1 (Rack) Drummer $\text{TOM1\_MD421}$ MD 421 $\text{OFF}$ $\text{+30dB}$ $\text{0dB}$
07 Tom 2 (Rack) Drummer $\text{TOM2\_MD421}$ MD 421 $\text{OFF}$ $\text{+30dB}$ $\text{0dB}$
08 Tom 3 (Floor) Drummer $\text{TOM3\_D4}$ Audix D4 $\text{OFF}$ $\text{+28dB}$ $\text{0dB}$
09 Overhead L Drummer $\text{OH\_L\_KM184}$ KM 184 $\text{ON}$ $\text{+45dB}$ $\text{0dB}$
10 Overhead R Drummer $\text{OH\_R\_KM184}$ KM 184 $\text{ON}$ $\text{+45dB}$ $\text{0dB}$
11 Ride Cymbal Drummer $\text{RIDE\_KSM137}$ KSM 137 $\text{ON}$ $\text{+40dB}$ $\text{10dB}$
12 Drum Room Stage Ambience $\text{DRUM\_ROOM\_RIBBON}$ Ribbon Mic $\text{OFF}$ $\text{+50dB}$ $\text{0dB}$
13 Percussion 1 Aux Percussionist $\text{PERC1\_E904}$ e904 $\text{ON}$ $\text{+35dB}$ $\text{0dB}$
14 Percussion 2 Aux Percussionist $\text{PERC2\_BETA98A}$ Beta 98A $\text{ON}$ $\text{+30dB}$ $\text{0dB}$
15 Talkback Mic Stage Manager $\text{TALKBACK\_SM58}$ SM58 $\text{ON}$ $\text{+20dB}$ $\text{0dB}$
16 Spare/Utility N/A $\text{SPARE\_UTILITY}$ N/A $\text{OFF}$ $\text{0dB}$ $\text{0dB}$

v=0
o=DrumKit – 16ch 3046777894 3046777894 IN IP4 192.168.1.10
s=Festival Drum Patch
c=IN IP4 192.168.1.10
t=0 0
m=audio 40000 RTP/AVP 97
a=rtpmap:97 L16/48000/16
a=sendrecv
a=mid:DRUMS16

a=Channel:01
a=label:Kick In
a=track-name:KICK_IN_BETA91A
a=i:Kick In – Low-frequency shell resonance.
a=ssrc:10000001
a=mic-info:Mic=Beta 91A; P48=OFF; Gain=+10dB; Pad=0db

a=Channel:02
a=label:Kick Out
a=track-name:KICK_OUT_D6
a=i:Kick Out – Beater attack and air movement.
a=ssrc:10000002
a=mic-info:Mic=Audix D6; P48=OFF; Gain=+25dB; Pad=0db

a=Channel:03
a=label:Snare Top
a=track-name:SNARE_TOP_SM57
a=i:Snare Top – Primary snare drum sound and attack.
a=ssrc:10000003
a=mic-info:Mic=SM57; P48=OFF; Gain=+35dB; Pad=0db

a=Channel:04
a=label:Snare Bottom
a=track-name:SNARE_BOT_E604
a=i:Snare Bottom – Snare wires for sizzle/snap.
a=ssrc:10000004
a=mic-info:Mic=e604; P48=OFF; Gain=+30dB; Pad=0db

a=Channel:05
a=label:Hi-Hat
a=track-name:HIHAT_C451B
a=i:Hi-Hat – Cymbals, rhythm, and clarity.
a=ssrc:10000005
a=mic-info:Mic=C451B; P48=ON; Gain=+40dB; Pad=10dB

a=Channel:06
a=label:Tom 1 (Rack)
a=track-name:TOM1_MD421
a=i:Tom 1 (Rack) – High rack tom resonance and attack.
a=ssrc:10000006
a=mic-info:Mic=MD 421; P48=OFF; Gain=+30dB; Pad=0db

a=Channel:07
a=label:Tom 2 (Rack)
a=track-name:TOM2_MD421
a=i:Tom 2 (Rack) – Mid rack tom resonance and attack.
a=ssrc:10000007
a=mic-info:Mic=MD 421; P48=OFF; Gain=+30dB; Pad=0db

a=Channel:08
a=label:Tom 3 (Floor)
a=track-name:TOM3_D4
a=i:Tom 3 (Floor) – Low floor tom resonance and thump.
a=ssrc:10000008
a=mic-info:Mic=Audix D4; P48=OFF; Gain=+28dB; Pad=0db

a=Channel:09
a=label:Overhead L
a=track-name:OH_L_KM184
a=i:Overhead L – Stereo image, cymbals, and kit balance.
a=ssrc:10000009
a=mic-info:Mic=KM 184; P48=ON; Gain=+45dB; Pad=0db

a=Channel:10
a=label:Overhead R
a=track-name:OH_R_KM184
a=i:Overhead R – Stereo image, cymbals, and kit balance.
a=ssrc:10000010
a=mic-info:Mic=KM 184; P48=ON; Gain=+45dB; Pad=0db

a=Channel:11
a=label:Ride Cymbal
a=track-name:RIDE_KSM137
a=i:Ride Cymbal – Dedicated input for ride stick definition.
a=ssrc:10000011
a=mic-info:Mic=KSM 137; P48=ON; Gain=+40dB; Pad=10dB

a=Channel:12
a=label:Drum Room
a=track-name:DRUM_ROOM_RIBBON
a=i:Drum Room – Ambient sound for space and size (mono).
a=ssrc:10000012
a=mic-info:Mic=Ribbon Mic; P48=OFF; Gain=+50dB; Pad=0db

a=Channel:13
a=label:Percussion 1
a=track-name:PERC1_E904
a=i:Percussion 1 – Primary percussion (e.g., Shaker, Tambourine).
a=ssrc:10000013
a=mic-info:Mic=e904; P48=ON; Gain=+35dB; Pad=0db

a=Channel:14
a=label:Percussion 2
a=track-name:PERC2_BETA98A
a=i:Percussion 2 – Secondary percussion (e.g., Conga/Bongo).
a=ssrc:10000014
a=mic-info:Mic=Beta 98A; P48=ON; Gain=+30dB; Pad=0db

a=Channel:15
a=label:Talkback Mic
a=track-name:TALKBACK_SM58
a=i:Talkback Mic – Communication from the stage.
a=ssrc:10000015
a=mic-info:Mic=SM58; P48=ON; Gain=+20dB; Pad=0db

a=Channel:16
a=label:Spare/Utility
a=track-name:SPARE_UTILITY
a=i:Spare/Utility – Reserved for last-minute needs or failures.
a=ssrc:10000016
a=mic-info:Mic=N/A; P48=OFF; Gain=0dB; Pad=0db

 

💡 Proposal: SDP Extension for Live Program & Ancillary Data

 

The core idea is to define a new set of media-level attributes that convey dynamic, human-readable, or system-critical metadata for each stream identified by its SSRC (Synchronization Source Identifier) or a=label.

 

1. New SDP Attributes for Metadata

 

We would define new media-level attributes (a=) to carry specific types of operational data. These attributes should be scoped to a specific stream using the a=label attribute, as defined in RFC 4574.

That is an excellent proposal. Extending SDP to carry rich, flow-specific metadata—like channel labels, track names, and operational status—moves it far beyond simple media negotiation and into the realm of a unified control and inventory protocol for all audio streams. This concept can be formalized as an SDP Extension for Live Program and Ancillary Data.

Here is a proposal for making SDP useful for this purpose, focusing on specific custom attributes and their applications.


💡 Proposal: SDP Extension for Live Program & Ancillary Data

The core idea is to define a new set of media-level attributes that convey dynamic, human-readable, or system-critical metadata for each stream identified by its SSRC (Synchronization Source Identifier) or a=label.

1. New SDP Attributes for Metadata

We would define new media-level attributes (a=) to carry specific types of operational data. These attributes should be scoped to a specific stream using the a=label attribute, as defined in RFC 4574.

Attribute Name Scope Purpose Example Value
a=program-id Session-Level (s=) Unique identifier for the overall production (e.g., “WXYZ Morning Show”). a=program-id:WXYZ-MORN-004
a=flow-name Media-Level (m=) Human-readable name for the stream’s purpose (e.g., “Mix-Minus Feed,” “Main PGM L/R”). a=flow-name:PGM-MAIN-STEREO
a=channel-label Source-Level (a=label) Primary label for the control surface/monitoring (FOH channel strip, Monitor wedge, etc.). a=channel-label:LEAD_VOX
a=track-name Source-Level (a=label) Track name for recording or playback (Pro Tools, DAWs). a=track-name:KICK_IN_SM91A
a=display-data Source-Level (a=label) Generic string for UMD (Under Monitor Display) / Ancillary displays. a=display-data:Guest_Mic_3
a=status-check Source-Level (a=label) Critical status information, like phantom power or line level requirement. a=status-check:P48=ON; Lvl=MIC

2. Applications of Metadata-Driven Activities

By embedding this metadata in the SDP, the audio infrastructure becomes self-identifying and self-correcting.

📻 Radio/Broadcast: Now Playing & Ancillary Data

  • SDP Use: The primary program streams (PGM-MAIN-STEREO) would contain the dynamic data for now-playing information.

  • Action: A gateway device (SRC) monitors the a=track-name or a dedicated a=now-playing attribute that is updated via an SDP re-offer/update. This information is automatically fed into broadcast automation systems, RDS encoders, and online streaming metadata APIs. The $\text{SRC}$ ensures the $\text{L/R}$ program feed is correctly labeled for the entire chain.

🎙️ Live Stage: UMDs and Channel Labels

  • SDP Use: The $\text{FOH}$ console and monitor desk receive the SDP. The $\text{a=channel-label}$ attribute is read for every $\text{SSRC}$ (microphone).

  • Action: Console surfaces and rack UMDs (Under Monitor Displays) automatically populate their text fields with LEAD_VOX or KICK_IN_SM91A. There is no need for a manual text input step, eliminating labeling errors and speeding up console setup.

✅ Self-Correcting Patching and Inventory

  • SDP Use: The a=status-check and a=track-name attributes contain the exact physical requirements and intended use.

  • Action: When a stage patch tech connects a mic to the stage box, a networked device reads the SDP for that channel’s expected status.

    • Self-Correction: If the SDP demands P48=ON but the stage box has phantom power off for that line, the system can flash an error indicator or automatically enable the correct state.

    • Self-Identification: If the patch tech plugs a spare vocal mic into the channel meant for the Kick Drum’s KICK_IN_SM91A, the system instantly alerts the operator to a patch mismatch. The metadata guarantees the signal is routed and labeled correctly at every point in the flow.

By standardizing this descriptive information within SDP, we leverage the protocol’s established routing and negotiation mechanisms to achieve the goal of metadata-driven activities, making live productions faster, safer, and inherently more reliable

Empowering the user

Empowering the User: The Boeing vs. Airbus Philosophy in Software and Control System Design

In the world of aviation, the stark philosophical differences between Boeing and Airbus control systems offer a profound case study for user experience (UX) design in software and control systems. It’s a debate between tools that empower the user with ultimate control and intelligent assistance versus those that abstract away complexity and enforce protective boundaries. This fundamental tension – enabling vs. doing – is critical for any designer aiming to create intuitive, effective, and ultimately trusted systems.

The Core Dichotomy: Enablement vs. Automation

At the heart of the aviation analogy is the distinction between systems designed to enable a highly skilled user to perform their task with enhanced precision and safety, and systems designed to automate tasks, protecting the user from potential errors even if it means ceding some control.

Airbus: The “Doing It For You” Approach

Imagine a powerful, intelligent assistant that anticipates your needs and proactively prevents you from making mistakes. This is the essence of the Airbus philosophy, particularly in its “Normal Law” flight controls.

The Experience: The pilot provides high-level commands via a side-stick, and the computer translates these into safe, optimized control surface movements, continuously auto-trimming the aircraft.

The UX Takeaway:

Pros: Reduces workload, enforces safety limits, creates a consistent and predictable experience across the fleet, and can be highly efficient in routine operations. For novice users or high-stress environments, this can significantly lower the barrier to entry and reduce the cognitive load.

Cons: Can lead to a feeling of disconnect from the underlying mechanics. When something unexpected happens, the user might struggle to understand why the system is behaving a certain way or how to override its protective actions. The “unlinked” side-sticks can also create ambiguity in multi-user scenarios.

Software Analogy: Think of an advanced AI writing assistant that not only corrects grammar but also rewrites sentences for clarity, ensures brand voice consistency, and prevents you from using problematic phrases – even if you intended to use them for a specific effect. It’s safe, but less expressive. Or a “smart home” system that overrides your thermostat settings based on learned patterns, even when you want something different.

Boeing: The “Enabling You to Do It” Approach

Now, consider a sophisticated set of tools that amplify your skills, provide real-time feedback, and error-check your inputs, but always leave the final decision and physical control in your hands. This mirrors the Boeing philosophy.

The Experience: Pilots manipulate a traditional, linked yoke. While fly-by-wire technology filters and optimizes inputs, the system generally expects the pilot to manage trim and provides “soft limits” that can be overridden with sufficient force. The system assists, but the pilot remains the ultimate authority.

The UX Takeaway:

Pros: Fosters a sense of control and mastery, provides direct feedback through linked controls, allows for intuitive overrides in emergencies, and maintains the mental model of direct interaction. For expert users, this can lead to greater flexibility and a deeper understanding of the system’s behavior.

Cons: Can have a steeper learning curve, requires more active pilot management (e.g., trimming), and places a greater burden of responsibility on the user to stay within safe operating limits.

Software Analogy: This is like a professional photo editing suite where you have granular control over every aspect of an image. The software offers powerful filters and intelligent adjustments, but you’re always the one making the brush strokes, adjusting sliders, and approving changes. Or a sophisticated IDE (Integrated Development Environment) for a programmer: it offers powerful auto-completion, syntax highlighting, and debugging tools, but doesn’t write the code for you or prevent you from making a logical error, allowing you to innovate.

Designing for Trust: Error Checking Without Taking Over

The crucial design principle emerging from this comparison is the need for systems that provide robust error checking and intelligent assistance while preserving the user’s ultimate agency. The goal should be to create “smart tools,” not “autonomous overlords.”

Key Design Principles for Empowerment:

Transparency and Feedback: Users need to understand what the system is doing and why. Linked yokes provide immediate physical feedback. In software, this translates to clear status indicators, activity logs, and explanations for automated actions. If an AI suggests a change, explain its reasoning.

Soft Limits, Not Hard Gates: While safety is paramount, consider whether a protective measure should be an absolute barrier or a strong suggestion that can be bypassed in exceptional circumstances. Boeing’s “soft limits” allow pilots to exert authority when necessary. In software, this might mean warning messages instead of outright prevention, or giving the user an “override” option with appropriate warnings.

Configurability and Customization: Allow users to adjust the level of automation and assistance. Some users prefer more guidance, others more control. Provide options to switch between different “control laws” or modes that align with their skill level and current task.

Preserve Mental Models: Whenever possible, build upon existing mental models. Boeing’s yoke retains a traditional feel. In software, this means using familiar metaphors, consistent UI patterns, and avoiding overly abstract interfaces that require relearning fundamental interactions.

Enable, Don’t Replace: The most powerful tools don’t do the job for the user; they enable the user to do the job better, faster, and more safely. They act as extensions of the user’s capabilities, not substitutes.

The Future of UX: A Hybrid Approach

Ultimately, neither pure “Airbus” nor pure “Boeing” is universally superior. The ideal UX often lies in a hybrid approach, intelligently blending the strengths of both philosophies. For routine tasks, automation and protective limits are incredibly valuable. But when the unexpected happens, or when creativity and nuanced judgment are required, the system must gracefully step back and empower the human creator.

Designers must constantly ask: “Is this tool serving the user’s intent, or is it dictating it?” By prioritizing transparency, configurable assistance, and the user’s ultimate authority, we can build software and control systems that earn trust, foster mastery, and truly empower those who use them.

Putting the Mechanics into Quantum Mechanics

As we explore the frontier of quantum computing, we’re not just grappling with abstract concepts like superposition and entanglement—we’re engineering systems that manipulate light, matter, and energy at their most fundamental levels. In many ways, this feels like a return to analog principles, where computation is continuous rather than discrete.

A Return to Analog Thinking

Quantum systems inherently deal with waves—light waves, probability waves, electromagnetic waves. These are the same building blocks that analog computers once harnessed with remarkable efficiency. Analog systems excelled at handling infinite resolution calculations, where signals like video, sound, and RF were treated as continuous phenomena:

  • Video is light being redirected.
  • Sound is pressure waves propagating.
  • RF is electromagnetic waves traveling from point to point.

The challenge now is: how do we process continuously varying signals at the speed of light, without being bottlenecked by digital discretization?

Light as Information

I often joke that light moves at the speed of light—until it’s put on a network. But in the quantum realm, we’re literally dealing with light as both input and output. That changes the paradigm entirely.

To “put the mechanics into quantum mechanics” means:

  • Designing systems that physically embody quantum principles.
  • Treating light not just as a carrier of information, but as the information itself.
  • Building architectures that process analog signals at quantum scales, leveraging phase, amplitude, and polarization as computational resources.

Engineering Quantum Behavior

In this paradigm, we’re not just simulating quantum behavior—we’re engineering it. Quantum computing isn’t just about qubits flipping between 0 and 1; it’s about manipulating the very nature of reality to perform computation. This requires a deep understanding of both the physics and the engineering required to build systems that operate at the atomic and photonic level.

We’re entering an era where the boundaries between physics, computation, and communication blur. And perhaps, by revisiting the principles of analog computation through the lens of quantum mechanics, we’ll unlock new ways to process information—at the speed of light, and with the precision of nature itself.

The Most Powerful Computers You’ve Never Heard Of

 

Why “Red” and “Blue” Are Misleading in Network Architecture

In network design, naming conventions matter. They shape how engineers think about systems, how teams communicate, and how failures are diagnosed. Among the more popular—but problematic—naming schemes are “red” and “blue” architectures. While these color-coded labels may seem harmless or even intuitive, they often obscure the true nature of system behavior, especially in environments where redundancy is partial and control mechanisms are not fully mirrored.

“When you centralize the wrong thing, you concentrate the blast… Resiliency you don’t practice – is resiliency you don’t have” – David Plumber

The Illusion of Symmetry

The use of “red” and “blue” implies a kind of symmetrical duality—two systems operating in parallel, equally capable, equally active. This might be true in some high-availability setups, but in many real-world architectures, one side is clearly dominant. Whether due to bandwidth, control logic, or failover behavior, the systems are not truly equal. Calling them “red” and “blue” can mislead engineers into assuming a level of redundancy or balance that simply doesn’t exist.

Why “Main” and “Failover” Are Better

A more accurate and practical naming convention is “main” and “failover.” These terms reflect the intentional asymmetry in most network designs:

  • Main: The primary path or controller, responsible for normal operations.
  • Failover: A backup that activates only when the main system fails or becomes unreachable.

This terminology makes it clear that the system is not fully redundant—there is a preferred path, and a contingency path. It also helps clarify operational expectations, especially during troubleshooting or disaster recovery.

The Problem with “Primary” and “Secondary”

While “primary” and “secondary” are common alternatives, they carry their own baggage. These terms often imply that both systems are active and cooperating, which again may not reflect reality. In many architectures, the secondary system is passive, waiting to take over only in specific failure scenarios. Using “secondary” can lead to confusion about whether it’s actively participating in control or data flow.

Naming Should Reflect Behavior

Ultimately, naming conventions should reflect actual system behavior, not just abstract design goals. If one path is dominant and the other is a backup, call them main and failover. If both are active and load-balanced, then perhaps red/blue or A/B makes sense—but only with clear documentation.

Misleading names can lead to misconfigured systems, delayed recovery, and poor communication between teams. Precision in naming is not just pedantic—it’s operationally critical.

Alternative Terminology for Primary / Secondary Roles

  • Anchor / Satellite
  • Driver / Follower
  • Coordinator / Participant
  • Source / Relay
  • Lead / Support
  • Commander / Proxy
  • Origin / Echo
  • Core / Edge
  • Root / Branch
  • Beacon / Listener
  • Pilot / Wingman
  • Active / Passive
  • Initiator / Responder
  • Principal / Auxiliary
  • Mainline / Standby

using GPI pins on an arduino to run a keyboard

 

#include <Keyboard.h>

// Define the GPIO pins for CTRL+A, CTRL+B, CTRL+C, and CTRL+D keys
#define A_PIN 2
#define B_PIN 3
#define C_PIN 4
#define D_PIN 5

void setup() {
// Set up the GPIO pins as inputs with pull-up resistors
pinMode(A_PIN, INPUT_PULLUP);
pinMode(B_PIN, INPUT_PULLUP);
pinMode(C_PIN, INPUT_PULLUP);
pinMode(D_PIN, INPUT_PULLUP);

// Initialize the keyboard library
Keyboard.begin();
}

void loop() {
// Check if the CTRL+A pin is pressed
if (digitalRead(A_PIN) == LOW) {
// Press and release the CTRL+A key combination
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(‘a’);
delay(50);
Keyboard.releaseAll();
}

// Check if the CTRL+B pin is pressed
if (digitalRead(B_PIN) == LOW) {
// Press and release the CTRL+B key combination
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(‘b’);
delay(50);
Keyboard.releaseAll();
}

// Check if the CTRL+C pin is pressed
if (digitalRead(C_PIN) == LOW) {
// Press and release the CTRL+C key combination
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(‘c’);
delay(50);
Keyboard.releaseAll();
}

// Check if the CTRL+D pin is pressed
if (digitalRead(D_PIN) == LOW) {
// Press and release the CTRL+D key combination
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(‘d’);
delay(50);
Keyboard.releaseAll();
}

// Wait for a short period of time before checking the pins again
delay(10);
}

Arduino sketch – keyboard keys pressed with gpi

#include KEYBOARD.h

const int F9_PIN = 2;
const int F10_PIN = 3;
const int F9_LED_PIN = 4;
const int F10_LED_PIN = 5;

void setup() {
Keyboard.begin();
pinMode(F9_PIN, INPUT_PULLUP);
pinMode(F10_PIN, INPUT_PULLUP);
pinMode(F9_LED_PIN, OUTPUT);
pinMode(F10_LED_PIN, OUTPUT);
}

void loop() {
if (digitalRead(F9_PIN) == LOW) {
Keyboard.press(KEY_F9);
digitalWrite(F9_LED_PIN, HIGH);
delay(100);
Keyboard.release(KEY_F9);
digitalWrite(F9_LED_PIN, LOW);
}

if (digitalRead(F10_PIN) == LOW) {
Keyboard.press(KEY_F10);
digitalWrite(F10_LED_PIN, HIGH);
delay(100);
Keyboard.release(KEY_F10);
digitalWrite(F10_LED_PIN, LOW);
}
}

Python OSC device – Motarized fader for volume + mute switch and solo switch

import reapy
import OSC

# Create an OSC client to send messages to Reaper
client = OSC.OSCClient()
client.connect(("127.0.0.1", 8000))

# Create an OSC server to receive messages from the fader and switches
server = OSC.OSCServer(("127.0.0.1", 9000))

def handle_volume(path, tags, args, source):
volume = args[0]
# Set the volume of the track using the Reaper API
reapy.connect()
track = reapy.Track(1)
track.volume = volume
reapy.disconnect()

# Add a callback for the volume fader
server.addMsgHandler("/volume", handle_volume)

def handle_mute(path, tags, args, source):
mute = args[0]
# Set the mute of the track using the Reaper API
reapy.connect()
track = reapy.Track(1)
track.mute = mute
reapy.disconnect()

# Add a callback for the mute switch
server.addMsgHandler("/mute", handle_mute)

def handle_solo(path, tags, args, source):
solo = args[0]
# Set the solo of the track using the Reaper API
reapy.connect()
track = reapy.Track(1)
track.solo = solo
reapy.disconnect()

# Add a callback for the solo switch
server.addMsgHandler("/solo", handle_solo)

# Run the OSC server
st = threading.Thread(target=server.serve_forever)
st.start()

BESKAR2D2 – test board with RJ45

#include <ReefwingSBUS.h>
#define MIN_LEFT_ROLL    -255
#define MAX_LEFT_ROLL     255
#define MIN_LEFT_PITCH    -255
#define MAX_LEFT_PITCH     255
#define MIN_RIGHT_ROLL   -255
#define MAX_RIGHT_ROLL    255
#define MIN_RIGHT_PITCH   -255
#define MAX_LEFT_PITCH    255
#define MIN_SBUS          200
#define MAX_SBUS          1800
//#define SWITCH_ON         991
SBUS RX_from_RADIOLINK(Serial3);
uint16_t channels[16];
uint16_t lostFrameCtr = 0;
uint16_t sbusChannel6 = 0, sbusChannel7 = 0, sbusChannel8 = 0, sbusChannel5 = 0, rxMode = 0;
int16_t sbusChannel1 = 0, sbusChannel2 = 0, sbusChannel3 = 0, sbusChannel4 = 0;
bool failSafe;
bool lostFrame;
bool armed = false;
void setup() {
  //  Start Serial and wait for connection from computer
  Serial.begin(115200);
  while (!Serial);
  RX_from_RADIOLINK.begin();
//BLUE RJ45 WIRE A
  pinMode(26, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(28, OUTPUT);
  pinMode(29, OUTPUT);
//wHITE WIRE  RJ45 WIRE b
  pinMode(30, OUTPUT);
  pinMode(31, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(33, OUTPUT);
//BLUE RJ45 WIRE B
  pinMode(34, OUTPUT);
  pinMode(35, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(37, OUTPUT);
//WHITE RJ45 WIRE B
  pinMode(38, OUTPUT);
  pinMode(39, OUTPUT);
  pinMode(40, OUTPUT);
  pinMode(41, OUTPUT);
//GREY RJ45 WIRE A
  pinMode(45, OUTPUT);//this is capable of PWM//speed
  pinMode(49, OUTPUT);//direction
  pinMode(50, OUTPUT);//BRAKE
  pinMode(51, OUTPUT);//STOP
//GREY RJ45 WIRE B
  pinMode(44, OUTPUT);//this is capable of PWM  //SPEED
  pinMode(48, OUTPUT);//DIRECTION
  pinMode(46, OUTPUT);//BRAKE
  pinMode(47, OUTPUT);//STOP
}
void loop() {
  // Check for a valid SBUS packet from the RX_from_RADIOLINK receiver
  if (RX_from_RADIOLINK.read(&channels[0], &failSafe, &lostFrame)) {
   //Scale the joysticks to the min and max
    sbusChannel1 = map(channels[0], MIN_SBUS, MAX_SBUS, MIN_LEFT_ROLL, MAX_LEFT_ROLL);
    sbusChannel2  = map(channels[1], MIN_SBUS, MAX_SBUS,  MAX_LEFT_PITCH,MIN_LEFT_PITCH);
    sbusChannel4 = map(channels[3], MIN_SBUS, MAX_SBUS, MIN_RIGHT_PITCH, MAX_LEFT_PITCH);
    sbusChannel3 = map(channels[2], MIN_SBUS, MAX_SBUS, MIN_RIGHT_ROLL, MAX_RIGHT_ROLL);
    //  AUX Channels
    sbusChannel5 = channels[4];
    sbusChannel6     = channels[5];
    sbusChannel7    = channels[6];
    sbusChannel8    = channels[7];
    rxMode   = channels[8];
    if (lostFrame) { lostFrameCtr++; }
  //LEFT SWITCH
  switch (sbusChannel7) {
    case 200:
      Serial.print(“LS”);Serial.print(“A”);Serial.print(“\t”);
                digitalWrite(31, HIGH);
                  digitalWrite(32, LOW);
                  digitalWrite(33, LOW);
            break;
    case 1000:
      Serial.print(“LS”);Serial.print(“B”);Serial.print(“\t”);
                   digitalWrite(31, LOW);
                  digitalWrite(32,HIGH);
                  digitalWrite(33, LOW);
      break;
    case 1800:
      Serial.print(“LS”);Serial.print(“C”);Serial.print(“\t”);
      digitalWrite(31, LOW);
                  digitalWrite(32, LOW);
                  digitalWrite(33, HIGH);
      break;
    default:
     Serial.println(“Invalid value”);
  }
/////////////////////////////// LEFT VOLUME
      Serial.print(“LV”);Serial.print(sbusChannel8); Serial.print(“\t”);
////LEFT X
        Serial.print(“LX”);Serial.print(sbusChannel4); Serial.print(“\t”);
      if (sbusChannel4 >= -255 && sbusChannel4 < -50) {
    // sbusChannel is within the range from -100 to -50
                  digitalWrite(38, HIGH);
                  digitalWrite(39, HIGH);
                  digitalWrite(40, LOW);
                  digitalWrite(41, LOW);
} else if (sbusChannel4 >= -50 && sbusChannel4 < -10) {
    // sbusChannel is within the range from -50 to -10
                   digitalWrite(38, HIGH);
                  digitalWrite(39, LOW);
                  digitalWrite(40, LOW);
                  digitalWrite(41, LOW);
} else if (sbusChannel4 >= -10 && sbusChannel4 < 10) {
    // sbusChannel is within the range from -10 to 10
                  digitalWrite(38, LOW);
                  digitalWrite(39, LOW);
                  digitalWrite(40, LOW);
                  digitalWrite(41, LOW);
} else if (sbusChannel4 >= 10 && sbusChannel4 < 50) {
    // sbusChannel is within the range from 10 to 50
                  digitalWrite(38, LOW);
                  digitalWrite(39, LOW);
                  digitalWrite(40, LOW);
                  digitalWrite(41, HIGH);
} else if (sbusChannel4 >= 50 && sbusChannel4 <= 255) {
    // sbusChannel is within the range from 50 to 100
                  digitalWrite(38, LOW);
                  digitalWrite(39, LOW);
                  digitalWrite(40, HIGH);
                  digitalWrite(41, HIGH);
} else {
    // sbusChannel is outside of all of the specified ranges
}
//////////////////////LEFT Y AXIS
    Serial.print(“LY”);Serial.print(sbusChannel3); Serial.print(“\t”);
      if (sbusChannel3 >= -255 && sbusChannel3 < -50) {
    // sbusChannel is within the range from -100 to -50
                  analogWrite(45,fabs(sbusChannel3) );//speed
                  digitalWrite(49, LOW);//direction
                  digitalWrite(50, LOW);//BRAKE
                  digitalWrite(51, LOW);//STOP//
Serial.print(“RF”);
} else if (sbusChannel3 >= -50 && sbusChannel3 < -10) {
    // sbusChannel is within the range from -50 to -10
                  analogWrite(45,fabs(sbusChannel1) );//speed
                  digitalWrite(49, LOW);//direction
                  digitalWrite(50, HIGH);//BRAKE
                  digitalWrite(51, LOW);//STOP//
Serial.print(“RS”);
} else if (sbusChannel3 >= -10 && sbusChannel3 < 10) {
    // sbusChannel is within the range from -10 to 10
                   analogWrite(45,fabs(sbusChannel3) );//speed
                  digitalWrite(49, LOW);//direction
                  digitalWrite(50, HIGH);//BRAKE
                  digitalWrite(51, HIGH);//STOP//
Serial.print(“SS”);
} else if (sbusChannel3 >= 10 && sbusChannel3 < 50) {
    // sbusChannel is within the range from 10 to 50
                  analogWrite(45,fabs(sbusChannel3) );//speed
                  digitalWrite(49, HIGH);//direction
                  digitalWrite(50, HIGH);//BRAKE
                  digitalWrite(51, LOW);//STOP//
Serial.print(“FS”);
} else if (sbusChannel3 >= 50 && sbusChannel3 <= 255) {
    // sbusChannel is within the range from 50 to 100
                  analogWrite(45,fabs(sbusChannel3) );//speed
                  digitalWrite(49, HIGH);//direction
                  digitalWrite(50, LOW);//BRAKE
                  digitalWrite(51, LOW);//STOP//
Serial.print(“FF”);
} else {
    // sbusChannel is outside of all of the specified ranges
}
 Serial.print(“\t”);
 Serial.print(“\t”);
 Serial.print(“\t”);
//////////////////////////////
//RIGHT SIDE OF CONTROLLER
/////////////////////////////
////////////////////////////////
    Serial.print(“RX”);Serial.print(sbusChannel1); Serial.print(“\t”);
      if (sbusChannel1 >= -255 && sbusChannel1 < -50) {
    // sbusChannel is within the range from -100 to -50
                  digitalWrite(34, HIGH);
                  digitalWrite(35, HIGH);
                  digitalWrite(36, LOW);
                  digitalWrite(37, LOW);
} else if (sbusChannel1 >= -50 && sbusChannel1 < -10) {
    // sbusChannel is within the range from -50 to -10
                   digitalWrite(34, HIGH);
                  digitalWrite(35, LOW);
                  digitalWrite(36, LOW);
                  digitalWrite(37, LOW);
} else if (sbusChannel1 >= -10 && sbusChannel1 < 10) {
    // sbusChannel is within the range from -10 to 10
digitalWrite(34, LOW);
                  digitalWrite(35, LOW);
                  digitalWrite(36, LOW);
                  digitalWrite(37, LOW);
} else if (sbusChannel1 >= 10 && sbusChannel1 < 50) {
    // sbusChannel is within the range from 10 to 50
    digitalWrite(34, LOW);
                  digitalWrite(35, LOW);
                  digitalWrite(36, LOW);
                  digitalWrite(37, HIGH);
} else if (sbusChannel1 >= 50 && sbusChannel1 <= 255) {
    // sbusChannel is within the range from 50 to 100
    digitalWrite(34, LOW);
                  digitalWrite(35, LOW);
                  digitalWrite(36, HIGH);
                  digitalWrite(37, HIGH);
} else {
    // sbusChannel is outside of all of the specified ranges
}
///////////////////////////////////////RIGHT Y
    Serial.print(“RY”);Serial.print(sbusChannel2); Serial.print(“\t”);
      if (sbusChannel2 >= -255 && sbusChannel2 < -50) {
    // sbusChannel is within the range from -100 to -50
                  analogWrite(44,fabs(sbusChannel2) );//speed
                  digitalWrite(48, LOW);//direction
                  digitalWrite(46, LOW);//BRAKE
                  digitalWrite(47, LOW);//STOP
Serial.print(“RF”);
} else if (sbusChannel2 >= -50 && sbusChannel2 < -10) {
    // sbusChannel is within the range from -50 to -10
                   analogWrite(44,fabs(sbusChannel2) );//speed
                  digitalWrite(48, LOW);//direction
                  digitalWrite(46, HIGH);//BRAKE
                  digitalWrite(47, LOW);//STOP
Serial.print(“RS”);
} else if (sbusChannel2 >= -10 && sbusChannel2 < 10) {
    // sbusChannel is within the range from -10 to 10
                  analogWrite(44,fabs(sbusChannel2) );//speed
                  digitalWrite(48, LOW);//direction
                  digitalWrite(46, HIGH);//BRAKE
                  digitalWrite(47, HIGH);//STOP
Serial.print(“ST”);
} else if (sbusChannel2 >= 10 && sbusChannel2 < 50) {
    // sbusChannel is within the range from 10 to 50
                  analogWrite(44,fabs(sbusChannel2) );//speed
                  digitalWrite(48, HIGH);//direction
                  digitalWrite(46, LOW);//BRAKE
                  digitalWrite(47, LOW);//STOP
                Serial.print(“FS”);
} else if (sbusChannel2 >= 50 && sbusChannel2 <= 255) {
    // sbusChannel is within the range from 50 to 100
                  analogWrite(44,fabs(sbusChannel2) );//speed
                  digitalWrite(48, HIGH);//direction
                  digitalWrite(46, LOW);//BRAKE
                  digitalWrite(47, LOW);//STOP
                  Serial.print(“FF”);
} else {
    // sbusChannel is outside of all of the specified ranges
}
Serial.print(“\t”);
     //Serial.print(“RB”);Serial.print(sbusChannel6); Serial.print(“\t”);
switch (sbusChannel6) {
    case 200:
      Serial.print(“RB”);Serial.print(“O”);Serial.print(“\t”);
                  digitalWrite(26, LOW);
                  digitalWrite(30, LOW);
            break;
    case 1800:
    Serial.print(“RB”);  Serial.print(“P”);Serial.print(“\t”);
                  digitalWrite(26, HIGH);
                      digitalWrite(30, HIGH);
      break;
    default:
      Serial.print(“RB”);Serial.print(“Invalid value”);Serial.print(“\t”);
      digitalWrite(26, LOW);
      digitalWrite(30, LOW);
      break;
  }
;
  switch (sbusChannel5) {
    case 200:
      Serial.print(“RS”);Serial.print(“A”);Serial.print(“\t”);
                  digitalWrite(27, HIGH);
                  digitalWrite(28, LOW);
                  digitalWrite(29, LOW);
                  break;
    case 1000:
      Serial.print(“RS”);Serial.print(“B”);Serial.print(“\t”);
                  digitalWrite(27, LOW);
                  digitalWrite(28,HIGH);
                  digitalWrite(29, LOW);
                  break;
    case 1800:
    Serial.print(“RS”);  Serial.print(“C”);Serial.print(“\t”);
                  digitalWrite(27, LOW);
                  digitalWrite(28, LOW);
                  digitalWrite(29, HIGH);
      break;
    default:
      Serial.print(“RS”);Serial.print(“Invalid value”);Serial.print(“\t”);
                        digitalWrite(27, LOW);
                  digitalWrite(28, LOW);
                  digitalWrite(29, LOW);
  }
;
Serial.print(“\t”);
       Serial.println(rxMode);
  }
  delay(10);
}

Arduino Project – Digitally Controlled Analog Surround Sound Panning – Open Source

For your enjoyment:

Digitally Controlled Analog Surround Sound Panning

 

Presentation:

 

Circuit Explination:

 

Presentation documents:

0 – TPJ – Technical Presentation

0 – TPJ556-FINAL report DCASSP-COMPLETE

0 – TPJ556-FINAL report DCASSP-SCHEMATICS V1

 

 

Project Source Code:

Continue reading

Fixing Logitech trackball performance

I love these Logitech Marble Mouse trackballs, I have one for every computer.  After a few years they slow down physically.  Cleaning the dust off does not help enough, something different needed to be applied.  I’ve been researching lubricants and oils, doing some tests with households; but I think I’ve found the perfect fluid.  Ian Gomes of Union Sound Company made a recommendation a few years back for Penny and Giles faders.  A quick amazon search lead me to Lucas Silicone Shock fluid.  I must report that it is the perfect product for this application.  If you need a drop, I’ll send you a q-tip of it in the mail.

IMG_0553

Generating Code with spreadsheet for Keyboard Assignments of CADSOFT Eagle

I needed a way of Generating Code, lots of code.   In cadsoft eagle, the Keyboard Assignments are completely user customizable.  They have a script language that allows you to modify the software.  I’ve used hundreds of the ULP and SCRs and decided to write my own Generator.

Necessity is the mother of all innovation.  Screen Shot 2015-09-14 at 12.56.34 AM Screen Shot 2015-09-14 at 12.56.45 AM Screen Shot 2015-09-14 at 12.56.52 AM Screen Shot 2015-09-14 at 12.56.59 AM Screen Shot 2015-09-14 at 12.57.04 AM Screen Shot 2015-09-14 at 12.58.37 AM Screen Shot 2015-09-14 at 12.58.44 AM Screen Shot 2015-09-14 at 12.58.50 AM