Domanda

Esiste un modo portatile, non limitato da brevetti, per riprodurre file audio compressi in C#/.Net?Voglio riprodurre brevi suoni "jingle" su vari eventi che si verificano nel programma.

System.Media.SoundPlayer può gestire solo WAV, ma in genere sono troppo grandi per essere incorporati in un'applicazione scaricabile.L'MP3 è protetto da brevetti, quindi anche se esistesse un decoder/lettore completamente gestito non sarebbe libero di ridistribuirlo.Il miglior formato disponibile sembrerebbe essere OGG Vorbis, ma non ho avuto fortuna nel far funzionare le librerie C# Vorbis (sono riuscito a estrarre un PCM grezzo con csvorbis ma non so come riprodurlo dopo).

Non voglio né distribuire alcun file binario con la mia applicazione né dipendere da P/Invoke, poiché il progetto dovrebbe essere eseguito almeno su Windows e Linux.Sto bene con il raggruppamento di assembly .Net purché siano compatibili con la licenza con GPL.

[questa domanda è il seguito di a discussione sulla mailing list su mono-dev mailing list di un anno fa]

È stato utile?

Soluzione

Alla fine ho rivisitato questo argomento e, utilizzando l'aiuto di BrokenGlass durante la scrittura dell'intestazione WAVE, aggiornato csvorbis.Ho aggiunto un OggDecodeStream a cui è possibile passare System.Media.SoundPlayer per riprodurre semplicemente qualsiasi flusso Ogg Vorbis (compatibile).Utilizzo di esempio:

using (var file = new FileStream(oggFilename, FileMode.Open, FileAccess.Read))
{
  var player = new SoundPlayer(new OggDecodeStream(file));
  player.PlaySync();
}

"Compatibile" in questo caso significa "ha funzionato quando l'ho provato".Il decoder è completamente gestito, funziona bene su Microsoft .Net - al momento sembra esserci una regressione in Mono SoundPlayer che provoca distorsione.

obsoleto:

System.Diagnostics.Process.Start("fullPath.mp3");

Sono sorpreso ma il metodo menzionato da Dinah funziona davvero.Tuttavia, stavo pensando di suonare brevi suoni "jingle" su vari eventi che si verificano nel programma, non voglio lanciare il lettore multimediale dell'utente ogni volta che ho bisogno di fare un "ping!" suono.

Per quanto riguarda il collegamento al progetto di codice, purtroppo si tratta solo di un wrapper P/Invoke.

Altri suggerimenti

Né voglio distribuire binari con la mia applicazione né dipendere da p/invochi, poiché il progetto dovrebbe essere eseguito almeno su Windows e Linux.Sto bene con il raggruppamento di assemblaggi .net purché siano compatibili con la licenza con GPL.

Sfortunatamente sarà impossibile evitare di distribuire file binari o evitare P/Invoke.Le librerie di classi .net utilizzano comunque P/Invoke, il codice gestito deve comunicare con l'API del sistema operativo non gestito ad un certo punto, per poter fare qualsiasi cosa.

La conversione del file OGG in PCM dovrebbe essere possibile nel codice gestito, ma poiché non è disponibile il supporto nativo per l'audio in .net, in realtà hai 3 opzioni:

  1. Chiama un programma esterno per riprodurre l'audio (come suggerito in precedenza)

  2. P/Richiama un modulo C per riprodurre il suono

  3. P/Richiama le API del sistema operativo per riprodurre l'audio.

(4.) Se esegui questo codice solo su Windows probabilmente potresti utilizzare semplicemente DirectShow.

P/Invoke può essere utilizzato in modo multipiattaformahttp://www.mono-project.com/Interop_with_Native_Libraries#Library_Names

Una volta che hai i tuoi dati PCM (utilizzando un OGG C Lib o un codice gestito, qualcosa del genere http://www.robburke.net/mle/mp3sharp/ ovviamente ci sono problemi di licenza con MP3), avrai bisogno di un modo per riprodurlo, sfortunatamente .net non fornisce alcuna valutazione diretta della tua scheda audio o metodi per riprodurre l'audio in streaming.È possibile convertire i file ogg in PCM all'avvio e quindi utilizzare System.Media.SoundPlayer per riprodurre i file wav generati.Il metodo attuale suggerito da Microsoft utilizza P/Invoke per accedere all'API di riproduzione del suono nel sistema operativo http://msdn.microsoft.com/en-us/library/ms229685.aspx

Un'API multipiattaforma per riprodurre l'audio PCM è OpenAL e dovresti essere in grado di riprodurre l'audio (PCM) utilizzando i collegamenti C# per OpenAL su www.taoframework.com, sfortunatamente dovrai copiare un numero di file DLL e .so con il tuo applicazione affinché funzioni quando viene distribuita, ma questo è, come ho spiegato prima, inevitabile.

Chiamare qualcosa che si trova in "System.Diagnostics" per riprodurre un suono mi sembra una pessima idea.Ecco a cosa serve questa funzione:

    //
    // Summary:
    //     Starts a process resource by specifying the name of a document or application
    //     file and associates the resource with a new System.Diagnostics.Process component.
    //
    // Parameters:
    //   fileName:
    //     The name of a document or application file to run in the process.
    //
    // Returns:
    //     A new System.Diagnostics.Process component that is associated with the process
    //     resource, or null, if no process resource is started (for example, if an
    //     existing process is reused).
    //
    // Exceptions:
    //   System.ComponentModel.Win32Exception:
    //     There was an error in opening the associated file.
    //
    //   System.ObjectDisposedException:
    //     The process object has already been disposed.
    //
    //   System.IO.FileNotFoundException:
    //     The PATH environment variable has a string containing quotes.

Penso che dovresti dare un'occhiata a fmod, che è la madre di tutte le API audio

per favore sentitevi liberi di sognare http://www.fmod.org/index.php/download#FMODExProgrammersAPI

Le API XNA Audio funzionano bene nelle applicazioni .net/c# e funzionano magnificamente per questa applicazione.Attivazione basata sugli eventi, insieme alla riproduzione simultanea di più suoni.Esattamente quello che vuoi.Oh, e anche la compressione.

Bene, dipende dalle leggi relative ai brevetti in un dato paese, ma non c'è modo di scrivere un decoder mp3 senza violare i brevetti, per quanto ne so.Penso che la migliore soluzione multipiattaforma e open source per il tuo problema sia GStreamer.Ha collegamenti C#, che si evolvono rapidamente.Tuttavia, utilizzare e creare GStreamer su Windows non è un compito facile. Qui è un buon punto di partenza. Banshee project utilizza questo approccio, ma non è ancora realmente utilizzabile su Windows (tuttavia, ci sono alcune build notturne quasi funzionanti). FMOD è anche una buona alternativa.Sfortunatamente non è open source e trovo che la sua API sia in qualche modo in stile C.

È disponibile un decodificatore vorbis C# puro che è open source:

http://anonsvn.mono-project.com/viewvc/trunk/csvorbis/

Non sono sicuro che questo sia ancora rilevante.La soluzione più semplice sarebbe usare NAudio, che è un'API audio open source gestita scritta in C#.Un'altra cosa da provare sarebbe utilizzare ffmpeg e creare un processo per ffplay.exe (i binari giusti si trovano in build condivise).

Non c'è modo di farlo senza usare qualcos'altro per la gestione del gioco.

Utilizzando System.Diagnostic verrà avviato un software esterno e dubito che tu lo voglia, giusto?Vuoi solo che il file audio X venga riprodotto in sottofondo quando Y accade nel tuo programma, giusto?

Votato perché sembra una domanda interessante.:D

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top