Search code examples
javaaudiomouseeventkeyeventjavasound

Scan for a sound on a specific process


I wonder if there is a way to scan in Java for a certain volume in a predefined process. If this volume exceeds a certain dB value, a certain KeyEvent or MouseEvent should be executed only on this process, so this could also run in the background. I couldn't see a good way to implement this in Java so far, so I'm also wondering if and how this is possible. Thanks in advance!


Solution

  • Basic plan:

    • Set up the sound to play over a SourceDataLine (will not work for Clip)
    • During playback, convert the byte data to PCM (the exact algorithm will depend on the audio format)
    • apply an RMS filter algorithm to the PCM data (look up root mean square for more info)
    • if the RMS value exceeds a target value, send a notification (using a "loosely coupled" design pattern with minimal risk of blocking the audio playback).

    For reading data exposed by the SourceDataLine during playback, check the first example in the tutorial "Using Files and Format Converters", the point where the code reads the following:

      // Here, do something useful with the audio data that's 
      // now in the audioBytes array...
    

    As far as determining what RMS value corresponds to the desired trigger DB or loudness level, things can get quite complicated. Audio data is basically relative not absolute, and the values that the RMS algorithm gives can have different "perceived" loudness depending upon the frequency content of the sound. This post, How to get the volume level from PCM data discusses some of the complications encountered in this realm. But perhaps it is overthinking the issue, depending on what you are going for.