Pergunta

Existe uma maneira portátil e não restrita por patente de reproduzir arquivos de som compactados em C#/.Net?Quero reproduzir sons curtos de "jingle" em vários eventos que ocorrem no programa.

System.Media.SoundPlayer pode lidar apenas com WAV, mas normalmente são grandes demais para serem incorporados em um aplicativo para download.O MP3 é protegido por patentes, portanto, mesmo que existisse um decodificador/player totalmente gerenciado, sua redistribuição não seria gratuita.O melhor formato disponível parece ser o OGG Vorbis, mas não tive sorte em fazer nenhuma biblioteca C# Vorbis funcionar (consegui extrair um PCM bruto com csvorbis mas não sei como jogar depois).

Não quero distribuir nenhum binário com meu aplicativo nem depender do P/Invoke, pois o projeto deve rodar pelo menos em Windows e Linux.Não há problema em agrupar assemblies .Net, desde que sejam compatíveis com a licença GPL.

[esta pergunta é uma continuação de uma discussão na lista de discussão sobre mono-dev lista de discussão há um ano]

Foi útil?

Solução

Finalmente revisitei este tópico e, usando a ajuda de BrokenGlass ao escrever o cabeçalho WAVE, csvorbis atualizado.Eu adicionei um OggDecodeStream que pode ser passado para System.Media.SoundPlayer para simplesmente reproduzir qualquer stream Ogg Vorbis (compatível).Exemplo de uso:

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

'Compatível' neste caso significa 'funcionou quando experimentei'.O decodificador é totalmente gerenciado, funciona bem no Microsoft .Net - no momento, parece haver uma regressão no Mono SoundPlayer que causa distorção.

Desatualizado:

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

Estou surpreso, mas o método que Dinah mencionou realmente funciona.No entanto, eu estava pensando em jogar sons curtos "jingle" em vários eventos que ocorrem no programa, não quero lançar o Media Player do usuário cada vez que preciso fazer um 'ping!' som.

Quanto ao link do projeto de código - infelizmente, este é apenas um wrapper P/Invoke.

Outras dicas

Não quero distribuir binários com meu aplicativo nem depender de P/Invoke, pois o projeto deve ser executado pelo menos no Windows e no Linux.Estou bem com os conjuntos .NET, desde que sejam compatíveis com a licença com a GPL.

Infelizmente será impossível evitar a distribuição de binários ou evitar o P/Invoke.De qualquer forma, as bibliotecas de classes .net usam P/Invoke, o código gerenciado precisa se comunicar com a API do sistema operacional não gerenciado em algum momento, para fazer qualquer coisa.

A conversão do arquivo OGG em PCM deve ser possível no código gerenciado, mas como não há suporte nativo para áudio no .net, você realmente tem três opções:

  1. Chame um programa externo para reproduzir o som (como sugerido anteriormente)

  2. P/Invoque um módulo C para reproduzir o som

  3. P/Invoque as APIs do sistema operacional para reproduzir o som.

(4.) Se você estiver executando este código apenas no Windows, provavelmente poderá usar o DirectShow.

P/Invoke pode ser usado de forma multiplataformahttp://www.mono-project.com/Interop_with_Native_Libraries#Library_Names

Depois de ter seus dados PCM (usando uma OGG C Lib ou código gerenciado, algo como isto http://www.robburke.net/mle/mp3sharp/ é claro que há problemas de licenciamento com MP3), você precisará de uma maneira de reproduzi-lo. Infelizmente, o .net não fornece nenhuma avaliação direta para sua placa de som ou métodos para reproduzir streaming de áudio.Você pode converter os arquivos ogg em PCM na inicialização e, em seguida, usar System.Media.SoundPlayer para reproduzir os arquivos wav gerados.O método atual sugerido pela Microsoft usa P/Invoke para acessar a API de reprodução de som no sistema operacional http://msdn.microsoft.com/en-us/library/ms229685.aspx

Uma API de plataforma cruzada para reproduzir som PCM é OpenAL e você deve ser capaz de reproduzir som (PCM) usando as ligações c # para OpenAL em www.taoframework.com. Infelizmente, você precisará copiar vários arquivos DLL e .so com seu aplicativo para que funcione quando distribuído, mas isso é, como expliquei anteriormente, inevitável.

Chamar algo localizado em 'System.Diagnostics' para reproduzir um som parece uma péssima ideia para mim.Aqui está o que essa função serve:

    //
    // 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.

eu acho que você deveria dar uma olhada no fmod, que é a mãe de todas as APIs de áudio

por favor, sinta-se à vontade para sonhar http://www.fmod.org/index.php/download#FMODExProgrammersAPI

As APIs de áudio XNA funcionam bem em aplicativos .net/c# e funcionam perfeitamente para este aplicativo.Acionamento baseado em eventos, juntamente com reprodução simultânea de vários sons.Exatamente o que você deseja.Ah, e compressão também.

Bem, isso depende das leis relacionadas a patentes em um determinado país, mas não há como escrever um decodificador de mp3 sem violar patentes, até onde eu sei.Acho que a melhor solução multiplataforma e de código aberto para o seu problema é GStreamer.Possui ligações c#, que evoluem rapidamente.Usar e construir o GStreamer no Windows não é uma tarefa fácil. Aqui é um bom ponto de partida. alma penada O projeto usa essa abordagem, mas ainda não é realmente utilizável no Windows (no entanto, existem algumas compilações noturnas quase funcionais). FMOD também é uma boa alternativa.Infelizmente, não é de código aberto e acho que sua API tem, de alguma forma, estilo C.

Existe um decodificador C# vorbis puro disponível que é de código aberto:

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

Não tenho certeza se isso ainda é relevante.A solução mais simples seria usar NAudio, que é uma API de áudio de código aberto gerenciada escrita em C#.Outra coisa a tentar seria utilizar o ffmpeg e criar um processo para ffplay.exe (os binários corretos estão em compilações compartilhadas).

Não há como fazer isso sem usar outra coisa para lidar com o jogo.

Usar o System.Diagnostic irá lançar um software externo e duvido que você queira isso, certo?Você só quer que o arquivo de som X seja reproduzido em segundo plano quando Y acontecer no seu programa, certo?

Votado porque parece uma pergunta interessante.:D

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top