Symphonie ~ Music Player


Symphonie is a sleek, lightweight desktop music player built with Electron and powered by HTML5 capabilities, offering a clean interface for enjoying your local audio library. It supports popular formats including MP3, FLAC, AAC, M4A, OGG, WAV, OPUS. Features include playlist management, intuitive playback controls, track metadata display (title/artist), and shuffle functionality for a seamless listening experience.

Features:

  • Supported audio formats mp3,aac,m4a,wav,ogg,flac,opus and more
  • Drag and drop files/folders directly onto the player or playlist
  • Visualizer which can be enabled and disabled
  • Reorder tracks within the playlist using drag and drop
  • Select all tracks and delete in the playlist using Ctrl+A
  • Seamless integration with modern web technologies without relying on third-party libraries.
  • Supported Platforms Windows 10/11,Debian,Ubuntu,Arch Linux,Linux Mint,Fedora
Symphonie

sourceforge.net/projects/symphonie

OBS ~ win-capture-audio Plugin


An OBS plugin that allows capture of independent application audio streams on Windows, in a similar fashion to OBS’s game capture and Discord’s application streaming.


obsproject.com/forum/resources/win-capture-audio.1338
github.com/bozbez/win-capture-audio
gigazine.net/gsc_news/en/20211230-obs-win-capture-audio

OpenPiano ~ Virtual Piano For Windows


OpenPiano is a Windows desktop piano application that allows you to play, practice, and record music using your PC keyboard, mouse, or a MIDI device.

It supports real-time playback using SoundFonts and provides on-screen piano layouts for visual feedback while playing.

OpenPiano is designed to run entirely locally. It does not require accounts, cloud services, or an internet connection for core functionality.

  • 61-key and 88-key layouts with live key feedback
  • SoundFont support (.sf2 / .sf3) with bank and preset selection
  • Keyboard, mouse, and MIDI input support
  • Editable keybind mode with Save, Discard, and Ctrl+Z undo
  • Keyboard and mouse combo triggers with shared 61/88-key mapping
  • MIDI recording and .mid export
  • Real-time controls for volume, velocity, sustain, and transpose
  • Live stats for KPS, held keys, and polyphony
  • Theme, UI scale, animation speed, and key color customization
  • Built-in tutorial with an in-depth explanation of features
  • Offline local-first workflow with no account required

www.justagwas.com/projects/openpiano
github.com/Justagwas/openpiano
sourceforge.net/projects/openpiano

Alternative:

github.com/michele-perrone/OpenPiano

Echo In Mirror ~ Digital Audio Workstation


An open source DAW (Digital Audio Workstation) written in pure Kotlin.

Features:

  •  VST/VST3/AU plugin support
  •  Audio effects
  •  Audio sample support
  •  ASIO support
  •  MIDI edit
  •  Latency compensation
  •  Audio edit
  •  Audio recording
  •  Midi input
  •  Plugin api
  •  CLAP and ARA plugin support
  •  Android support
  •  iOS support

github.com/EchoInMirror/EchoInMirror

Lidify ~ Music Hosting & Discovery Tool


Lidify is built for music lovers who want the convenience of streaming services without sacrificing ownership of their library. Point it at your music collection, and Lidify handles the rest: artist discovery, personalized playlists, podcast subscriptions, and seamless integration with tools you already use like Lidarr and Audiobookshelf.

  • Stream your library – FLAC, MP3, AAC, OGG, and other common formats work out of the box
  • Automatic cataloging – Lidify scans your library and enriches it with metadata from MusicBrainz and Last.fm
  • Audio transcoding – Stream at original quality or transcode on-the-fly (320kbps, 192kbps, or 128kbps)
  • Ultra-wide support – Library grid scales up to 8 columns on large displays
Lidify Interface

github.com/Chevron7Locked/lidify
github.com/TheWicklowWolf/Lidify

PedalBoard ~ Python Audio Library


pedalboard is a Python library for working with audio: reading, writing, rendering, adding effects, and more. It supports most popular audio file formats and a number of common audio effects out of the box, and also allows the use of VST3® and Audio Unit formats for loading third-party software instruments and effects.

Features:

  • Built-in audio I/O utilities (pedalboard.io)
    • Support for reading and writing AIFF, FLAC, MP3, OGG, and WAV files on all platforms with no dependencies
    • Additional support for reading AAC, AC3, WMA, and other formats depending on platform
    • Support for on-the-fly resampling of audio files and streams with O(1) memory usage
    • Live audio effects via AudioStream
  • Built-in support for a number of basic audio transformations, including:
    • Guitar-style effects: ChorusDistortionPhaserClipping
    • Loudness and dynamic range effects: CompressorGainLimiter
    • Equalizers and filters: HighpassFilterLadderFilterLowpassFilter
    • Spatial effects: ConvolutionDelayReverb
    • Pitch effects: PitchShift
    • Lossy compression: GSMFullRateCompressorMP3Compressor
    • Quality reduction: ResampleBitcrush
  • Supports VST3® instrument and effect plugins on macOS, Windows, and Linux (pedalboard.load_plugin)
  • Supports instrument and effect Audio Units on macOS
  • Strong thread-safety, memory usage, and speed guarantees
    • Releases Python’s Global Interpreter Lock (GIL) to allow use of multiple CPU cores
      • No need to use multiprocessing!
    • Even when only using one thread:
      • Processes audio up to 300x faster than pySoX for single transforms, and 2-5x faster than SoxBindings (via iCorv)
      • Reads audio files up to 4x faster than librosa.load (in many cases)
  • Tested compatibility with TensorFlow – can be used in tf.data pipelines!

github.com/spotify/pedalboard

DLNA Music Controller ~ Manage DLNA Directly


Read a DLNA Media Server to select music to play on your DLNA Renderer

Scan the network for your Media Server (“Server”) and Renderer (“Renderer”) devices, select one of each and then from the main screen select the music you want to play, drilling into Albums, Artists, Genres (all defined by your Media Server). Any music you want to hear is called a track and is loaded onto the play queue. Then select Play button to listen to the track listed at the top of the queue. You can also create playlists and store your favorite tracks for playback.

Features:

  • DLNA
  • Media Server
  • Media Renderer
  • Play queue

sourceforge.net/projects/dlna-music-controller

Resources:

en.wikipedia.org/wiki/List_of_UPnP_AV_media_servers_and_clients

Foobar2000 ~ Album Based Beats Per Minute


Beats Per minute is great for playlist of songs sorted by BPM but it would be useful to sort albums by BPM as well. To do this the following script calculates an average of BPM information from each song of the album and write that value to ALBUM_AVG_BPM. Then just create a playlist sorted by artist then album_avg_bpm

SMP Album Average BPM Calculator Script

In the DUI, toggle layout and create a new panel or tab, then right click the new area and add a New UI Element, scroll down to the Utility section and select Spider Monkey Panel and click OK. Now right click the new Spider Monkey Panel and select Edit Panel Script. Select the entire contents on the new ‘Temporary File’ window and replace them with the following script.

Show full script

'use strict';

/*
====================================================
Album Average BPM Panel - FULL PRO v5
- Immediate feedback for buttons
- Status line in report section
- Progress bars appear immediately
- Logs skipped files
- Inconsistent albums listed
====================================================
*/

function RGB(r,g,b){ return (0xff000000 | (r<<16) | (g<<8) | b); }

////////////////////////////////////////////////////
// TitleFormats
////////////////////////////////////////////////////
const tf_album = fb.TitleFormat("%album%");
const tf_albumArtist = fb.TitleFormat("%album artist%");
const tf_artist = fb.TitleFormat("%artist%");
const tf_bpm = fb.TitleFormat("%bpm%");
const tf_existing = fb.TitleFormat("%album_avg_bpm%");

////////////////////////////////////////////////////
// UI Colours + Font
////////////////////////////////////////////////////
function getUIColours(){
    try{
        return { bg: window.GetColourDUI(1), text: window.GetColourDUI(0), accent: window.GetColourDUI(2) };
    }catch(e){
        return { bg: RGB(30,30,30), text: RGB(255,255,255), accent: RGB(0,200,0) };
    }
}

function getUIFont(){ try{ return window.GetFontDUI(0); } catch(e){ return gdi.Font("Segoe UI",13,0); } }

////////////////////////////////////////////////////
// Library cache
////////////////////////////////////////////////////
let libHandles = null;
function loadLibraryOnce(){ if(!libHandles) libHandles = fb.GetLibraryItems(); }

////////////////////////////////////////////////////
// State
////////////////////////////////////////////////////
let runningUpdate=false;
let reporting=false;
let updateIndex=0, updateTimer=0;
let reportIndex=0, reportTimer=0;
let currentAlbum="Idle", currentFile="";
let updates=0;

let totalFiles=0, totalAlbums={};
let missingBPM=0, zeroBPM=0, missingAlbumAvg=0;
let minBPM=999999, maxBPM=0;
let albumConsistency={}, inconsistentAlbums=0;
let skippedFiles=[];

let forceRecalc=false, useMedian=false;

////////////////////////////////////////////////////
// Layout
////////////////////////////////////////////////////
const LEFT_WIDTH = 280;
const buttonScan={x:20,y:50,w:220,h:50};
const buttonUpdate={x:20,y:110,w:220,h:50};
const buttonCopy={x:20,y:170,w:220,h:50};
const checkboxForce={x:20,y:240,size:20};
const checkboxMedian={x:20,y:270,size:20};

////////////////////////////////////////////////////
// Album BPM Update Logic
////////////////////////////////////////////////////
let albumsMap=[];

function buildAlbums(){
    loadLibraryOnce();
    albumsMap = [];
    let map={};

    for(let i=0;i400) continue; // Filter extreme BPMs

        let groupingArtist = albumArtist ? albumArtist : artist;
        let key = groupingArtist+"|||"+album;

        if(!map[key]){
            map[key]={ handles:new FbMetadbHandleList(), sum:0, count:0, hasExisting:true, existingValues:{} };
        }

        map[key].handles.Add(h);
        map[key].sum += bpm;
        map[key].count++;

        let albumAvg = tf_existing.EvalWithMetadb(h);
        if(albumAvg) map[key].existingValues[albumAvg]=true;

        if(!albumAvg) map[key].hasExisting=false;
    }

    albumsMap = Object.values(map);
}

function stopUpdateTimer(){ if(updateTimer){ window.ClearInterval(updateTimer); updateTimer=0; } }

function processUpdateNext(){
    if(!runningUpdate) return;

    if(updateIndex>=albumsMap.length){
        runningUpdate=false;
        stopUpdateTimer();
        currentAlbum="Finished";
        fb.ShowPopupMessage("Album BPM Update Finished. Updated Albums: "+updates);
        window.Repaint();
        return;
    }

    let data = albumsMap[updateIndex++];
    currentAlbum = tf_album.EvalWithMetadb(data.handles[0]);

    // Determine if update needed
    let inconsistent = Object.keys(data.existingValues).length > 1;
    if(!forceRecalc && !inconsistent) return;

    let avg=0;
    if(useMedian){
        let arr=[];
        for(let i=0;i<data.handles.Count;i++){
            let val=parseFloat(tf_bpm.EvalWithMetadb(data.handles[i]));
            if(!isNaN(val) && vala-b);
        let mid=Math.floor(arr.length/2);
        avg = arr.length%2===0 ? (arr[mid-1]+arr[mid])/2 : arr[mid];
    }else{
        avg = data.sum / data.count;
    }
    avg = avg.toFixed(2);

    let json=[];
    for(let i=0;i<data.handles.Count;i++){
        try{
            json.push({"ALBUM_AVG_BPM":avg});
        }catch(e){
            skippedFiles.push(data.handles[i].Path);
        }
    }

    try{
        data.handles.UpdateFileInfoFromJSON(JSON.stringify(json));
        updates++;
    }catch(e){
        for(let i=0;i0){
        currentAlbum = tf_album.EvalWithMetadb(albumsMap[0].handles[0]);
    }

    window.Repaint();
    updateTimer = window.SetInterval(processUpdateNext,100);
}

////////////////////////////////////////////////////
// Report Logic
////////////////////////////////////////////////////
let reportText="Press Scan Library.";

function stopReportTimer(){ if(reportTimer){ window.ClearInterval(reportTimer); reportTimer=0; } }

function processReportNext(){
    if(!reporting) return;
    let batch=500;

    for(let c=0;c<batch && reportIndex0){
                if(bpmmaxBPM) maxBPM=bpm;
            }
        }
        if(!albumAvg) missingAlbumAvg++;

        if(!albumConsistency[key]) albumConsistency[key]={};
        if(albumAvg) albumConsistency[key][albumAvg]=true;

        currentFile = groupingArtist+" - "+album;
    }

    if(reportIndex>=libHandles.Count){
        reporting=false;
        stopReportTimer();

        inconsistentAlbums=0;
        let inconsistentList=[];
        for(let k in albumConsistency){
            let vals=Object.keys(albumConsistency[k]);
            if(vals.length>1){
                inconsistentAlbums++;
                if(inconsistentList.length0?inconsistentList.join("\n"):"None"}

Skipped / Inaccessible Files:
${skippedFiles.length>0?skippedFiles.join("\n"):"None"}

Current Status: Idle

BPM Range:
- Lowest BPM found: ${minBPM===999999?"N/A":minBPM}
- Highest BPM found: ${maxBPM}`;
    }

    window.Repaint();
}

function startReport(){
    if(reporting) return;
    loadLibraryOnce();
    reportIndex=0;
    totalFiles=0; totalAlbums={};
    missingBPM=0; zeroBPM=0; missingAlbumAvg=0;
    minBPM=999999; maxBPM=0; albumConsistency={};
    skippedFiles=[];

    reporting=true;
    reportText="Scanning library...";

    // show first file immediately
    if(libHandles.Count>0){
        currentFile = tf_album.EvalWithMetadb(libHandles[0]) || "(No Album)";
    }

    window.Repaint();
    reportTimer = window.SetInterval(processReportNext,10);
}

////////////////////////////////////////////////////
// Drawing
////////////////////////////////////////////////////
function drawButton(gr,b,label,ui,font){
    gr.FillSolidRect(b.x,b.y,b.w,b.h,ui.accent);
    gr.DrawString(label,gdi.Font(font.Name,14,1),ui.text,b.x,b.y,b.w,b.h,0x11000000);
}

function drawCheckbox(gr,c,label,state,ui,font){
    gr.DrawRect(c.x,c.y,c.size,c.size,1,ui.text);
    if(state) gr.FillSolidRect(c.x+4,c.y+4,c.size-8,c.size-8,ui.accent);
    gr.DrawString(label,font,ui.text,c.x+28,c.y-2,300,24,0);
}

function on_paint(gr){
    let ui=getUIColours();
    let font=getUIFont();
    let titleFont=gdi.Font(font.Name,16,1);

    gr.FillSolidRect(0,0,window.Width,window.Height,ui.bg);

    // LEFT PANEL
    gr.DrawString("Album Avg BPM Tools",titleFont,ui.text,20,10,LEFT_WIDTH,30,0);
    drawButton(gr,buttonScan,"Scan Library",ui,font);
    drawButton(gr,buttonUpdate,"Run Album BPM Update",ui,font);
    drawButton(gr,buttonCopy,"Copy Report",ui,font);
    drawCheckbox(gr,checkboxForce,"Force Recalculate",forceRecalc,ui,font);
    drawCheckbox(gr,checkboxMedian,"Use Median Averaging",useMedian,ui,font);

    gr.DrawLine(LEFT_WIDTH,0,LEFT_WIDTH,window.Height,1,ui.text);

    // RIGHT PANEL - report text
    let statusText = reporting ? "Scanning: "+currentFile : runningUpdate ? "Updating Album BPM: "+currentAlbum : "Idle";
    let reportWithStatus = reportText.replace("Current Status: Idle","Current Status: "+statusText);

    gr.GdiDrawText(reportWithStatus,font,ui.text,
        LEFT_WIDTH+20,20,
        window.Width-(LEFT_WIDTH+40),
        window.Height-160,0); // leave 160px for progress bars

    // Progress bars
    const barHeight = 18;
    const margin = 8;
    const barYUpdate = window.Height - 2*barHeight - 2*margin;
    const barYScan   = window.Height - barHeight - margin;

    if(runningUpdate){
        let prog=Math.floor((updateIndex/albumsMap.length)*(window.Width-LEFT_WIDTH-40));
        gr.FillSolidRect(LEFT_WIDTH+20,barYUpdate,prog,barHeight,ui.accent);
        gr.DrawRect(LEFT_WIDTH+20,barYUpdate,window.Width-LEFT_WIDTH-40,barHeight,1,ui.text);
        gr.DrawString("Updating Album BPM: "+currentAlbum,font,ui.text,LEFT_WIDTH+20,barYUpdate-25,window.Width-LEFT_WIDTH-40,20,0);
    }

    if(reporting){
        let prog=Math.floor((reportIndex/libHandles.Count)*(window.Width-LEFT_WIDTH-40));
        gr.FillSolidRect(LEFT_WIDTH+20,barYScan,prog,barHeight,ui.accent);
        gr.DrawRect(LEFT_WIDTH+20,barYScan,window.Width-LEFT_WIDTH-40,barHeight,1,ui.text);
        gr.DrawString("Scanning: "+currentFile,font,ui.text,LEFT_WIDTH+20,barYScan-25,window.Width-LEFT_WIDTH-40,20,0);
    }
}

////////////////////////////////////////////////////
// Mouse
////////////////////////////////////////////////////
function on_mouse_lbtn_up(x,y){
    if(hit(buttonScan,x,y)) {
        startReport();
        reportText = "Scanning library...";
        currentFile = libHandles.Count>0 ? tf_album.EvalWithMetadb(libHandles[0]) || "(No Album)" : "Idle";
        window.Repaint();
    }
    if(hit(buttonUpdate,x,y)) {
        startUpdate();
        currentAlbum = albumsMap.length>0 ? tf_album.EvalWithMetadb(albumsMap[0].handles[0]) : "Preparing update...";
        window.Repaint();
    }
    if(hit(buttonCopy,x,y) && reportText){
        utils.SetClipboardText(reportText);
        fb.ShowPopupMessage("Report copied to clipboard.");
    }

    if(hitSquare(checkboxForce,x,y)){ forceRecalc=!forceRecalc; window.Repaint(); }
    if(hitSquare(checkboxMedian,x,y)){ useMedian=!useMedian; window.Repaint(); }
}

function hit(b,x,y){ return x>=b.x && x=b.y && y=c.x && x=c.y && y<=c.y+c.size; }

Album Avg BPM Tools Script

Resources:

https://github.com/stengerh/foo_bpm
https://github.com/NotSimone/foo_cnn_bpm
https://github.com/tom2tec/foobar2000-smp-album-average-bpm

Dancing QT ~  Player For Dancing Schools


Dancing QT is a combined music database and player application specially designed for dancing schools and equivalent applications. Key features are an easy-to-use interface, fast search capabilities, playlist management, exact pitching and crossfading.

Looking around the open source landscape for a while, I tried to find a music database and player that is suitable for use in a dancing school environment – without success. Most mixing applications tend to be too confusing for the intended audience, most players lack database searching capabilites and most song databases don’t know how to pitch 😦

Because of this, I decided to setup a new application – Dancing QT. It uses alsaplayer because of its excellent interface and pitching capabilities, it uses an embedded SQLite DBMS to maintain a song database, and it uses taglib to populate the database. The interface is written in C++ using Qt. Because of the alsaplayer dependency, the target platforms will be limited to environments providing alsaplayer.

Dancing QT Interface

dqt.sourceforge.net
sourceforge.net/projects/dqt

Cynthia ~ Multitrack MIDI Player


Reliably play midi music files from a folder or “.m3u” playlist. Adjust playback speed, volume and output device on the fly during playback. A large playback progress bar makes jumping forward and backward in time a breeze with just a single click or tap. Supports “.mid”, “.midi” and “.rmi” files in format 0 (single track) and format 1 (multi-track). Comes complete with 24 sample midis ready to play.

Features:

  • Dual play systems – Play Folder and Play List
  • Comes with 24 built-in sample midis on a virtual disk
  • Elapsed, Remaining and Total time readouts
  • Native “.m3u” playlist support (copy, paste, open, save, build)
  • Drag and drop midi files to play / add to playlist
  • Play Modes: Once, Repeat One, Repeat All, All Once, Random
  • Play Speed: 10% to 1,000% (1/10th to 10x)
  • Intro Mode: Play first 2s, 5s, 10s or 30s of midi
  • Rewind / Fast Forward by: 1s, 2s, 5s, 10s or 30s
  • Play on Start option – playback commences on app start
  • Always on Midi option – maintain connection to midi device for instant playback
  • Auto Fade In – eliminate loud or abrupt notes during rewind, fast forward or reposition operations
  • Playback Progress bar – click to reposition/jump backward or forward in time
  • Volume control with volume boost (up to 200%)
  • Play “.mid”, “.midi” and “.rmi” midi files in 0 and 1 formats
  • Custom built midi playback subsystem for high playback stability
  • Scrolling lyrics viewer
  • Detailed midi information panel
  • Tracks Panel: Realtime track data indicators with mute all, unmute all, and mute individual track options
  • Channels Panel: Realtime channel output volume indicators with peak level hold and variable hold time, unmute all, mute all, and mute individual channel options
  • Notes Panel: 128 realtime note usage indicators with variable hold time, 8-12 notes per line display, labels as letters or numbers, unmute all, mute all, and mute individual note options
  • Piano Panel: View realtime piano keystrokes on a 128, 88, 76, 61, 54, 49 or 37 key keyboard with animated and lit keystrokes
  • Piano: Mark middle C key, C + F keys, or all white keys
  • Transpose option: Shift all notes up or down music scale
  • Use an Xbox Controller to control Cynthia’s main functions – playback speed and volume, song position, display panels, song file navigation, jump to start of song, toggle fullscreen mode, etc
  • Large list capacity for handling thousands of midi files
  • Switch between up to 10 midi playback devices
  • Simple and easy to use
  • Options Window – Easily change app color, font and settings
  • Portable

sourceforge.net/projects/cynthia1
www.blaizenterprises.com/cynthia

BlackDiamond ~ Fruityloops Studio Clone


Fruityloops clone with sound samples using Fmodex lib

BlackDiamond (formerly Crazy Machine) is a project I neglected for years until I got back into making music. The package comes with free VST plugins and samples, and soon to be introduced at some point in time, perfect sequencer sample mixer playback thingamagiggy we are now back in full armor trying to create the wildest dreams of software working on BlackDiamond.

Features:

  • Six built in effects for each 16 channels Flange, Chorus, Compression, Echo, Distortion, Reverb
  • fruity loops style pattern manipulation
  • Written in FreeBasic, the most best freeware IDE compiler for basic language
  • Recent May 2019 re-programming to V3
  • VST and Dialog window support, switch plugins with a click
  • calculations are now down to the clock cycle to milliseconds
  • Load VST plugins, samples during playback.
  • View VST plugin dialog, which works when using SET MS method
  • SET MS (Alter VST plugin data) now very easily tuneable
  • Supports ASIO Interface and Microsoft Windows wave file writing

sourceforge.net/projects/jesuschristsuns

lipupini ~ Media File Organization System


Lipupini is a public domain platform for organizing computer files like images, videos, sounds and writings that you might want to display under your domain on the Internet. Lipupini aims to support RSS and Fediverse protocols.

github.com/lipupini/lipupini
lipupini-demo.dup.bz/@example