2016-08-23 7 views
1

最近、数学と音楽をリンクしたいので、「linux in tone in play」の方法に興味があります。私は*.mp3*.wavなどの音楽ファイルを使用する必要はありませんので、私はそれを行うシステムコールを使用したいと思います。私はインターネット上で研究を行ってきましたが、 '再生する方法音楽ファイルをプログラムに入れてください。linuxは音楽をどのように演奏しますか(ALSA)

Linux上にleds(/sys/class/leds/.../brightness)やusbs(/dev/usb/)のようなデバイスファイルがあると思っていました。私のコンピュータには/dev/audio/dev/dsp/dev/soundはありません。

私はLinuxが音楽ファイルをどのように再生しているのかを知りたいので、そこから始めて目標を達成していきたいと思います。

私の質問は、 "Linuxは音楽(ALSA)を再生する方法" の "Linuxで音楽[ファイル]を再生するにはどのように" ませですが、INSTEAD。 「プログラムでトーンを演奏する方法」についての回答も受け入れられます。

答えて

1

あなたの質問は、「誰かが私に魚の釣り方法を説明できるか」のようなものです。非常に多くの方法があり、多くのツールがあり、それぞれの答えは技術的には正しいものの、トローラーを操作する人から、フライフィッシャー、スピアフィッシャーまで、答える人の答えを示すだけです。
Audio on linuxは、ワイルドウエストの水のようなテーマです。「ウイスキーは飲み物に、水は戦うためのもの」です。ちょうど楽しみのための複雑さの考え方については、以下のリンクを試してみてください :

https://ubuntuforums.org/showthread.php?t=843012

http://alsa.opensrc.org/MultipleCards

しかし、あなたがコマンドラインから実行することができます(と書くことができる「トーン」の例を与えるために、コード、Pythonと特定のためのC)にあなたの箱の上のgstreamer-1.0をアップロードし、次のコマンドを実行します。

gst-launch-1.0 audiotestsrc freq=329.63 volume=0.5 ! autoaudiosink 

gst-launch-1.0 audiotestsrc freq=987.77 ! autoaudiosink 

gst-launch-1.0 audiotestsrc wave=2 freq=200 volume=0.2 ! tee name=t ! queue ! audioconvert ! autoaudiosink t. ! queue ! audioconvert ! libvisual_lv_scope ! videoconvert ! autovideosink 

次にチェックアウト:
https://gstreamer.freedesktop.org/documentation/plugins.html

注:gstreamerはフライフィッシング詐欺師のストーリーであり、戦闘の話です!ここで

は、あなたが一緒にプレイするためのいくつかのGtkコードです:

#!/usr/bin/env python 
import gi 
gi.require_version('Gst', '1.0') 
from gi.repository import Gst, GObject, Gtk 
class Tone(object): 

    def __init__(self): 
     window = Gtk.Window(Gtk.WindowType.TOPLEVEL) 
     window.set_title("Tone-Player") 
     window.set_default_size(500, 200) 
     window.connect("destroy", Gtk.main_quit, "WM destroy") 
     vbox = Gtk.VBox() 
     window.add(vbox) 
     self.tone_entry = Gtk.Entry() 
     self.tone_entry.set_text('300.00') 
     vbox.pack_start(self.tone_entry, False, False, 0) 
     self.button = Gtk.Button("Start") 
     vbox.add(self.button) 
     self.button.connect("clicked", self.start_stop) 
     window.show_all() 

     self.player = Gst.Pipeline.new("player") 
     source = Gst.ElementFactory.make("audiotestsrc", "tone-source") 
     audioconv = Gst.ElementFactory.make("audioconvert", "converter") 
     audiosink = Gst.ElementFactory.make("autoaudiosink", "audio-output") 
     self.player.add(source) 
     self.player.add(audioconv) 
     self.player.add(audiosink) 
     source.link(audioconv) 
     audioconv.link(audiosink) 

    def start_stop(self, w): 
     if self.button.get_label() == "Start": 
       self.button.set_label("Stop") 
       tone = float(self.tone_entry.get_text()) 
       self.player.get_by_name("tone-source").set_property("freq", tone) 
       self.player.set_state(Gst.State.PLAYING) 
     else: 
      self.player.set_state(Gst.State.NULL) 
      self.button.set_label("Start") 

GObject.threads_init() 
Gst.init(None) 
Tone() 
Gtk.main() 
+0

一度に2つの周波数を再生する方法はありますか? – Chromium

+0

最も単純な方法では、self.playerと同じ方法でself.player2を作成します。これにより、結合された出力が得られます。私はおそらく左右に分ける方法があると思いますが、あなた自身の研究をする必要があります。 –

+0

'audioconv'と' audiosink'の使い方は? – Chromium

1

ALSAは、多数のサウンドカードをサポートするカーネルドライバです。通常、サウンドシステムと直接対話したい低レベルのアプリケーションで使用されます。

ALSAにはlibrary APIがあります。いくつかの例についてはdocumentationを見て、正しい方向に助けてください。

ALSAを使用すると、バッファにアクセスしてサウンドデバイスで再生されるサンプルを挿入できます。これはPCM(Pulse-Code Modulation)で行われます。 ALSAを使用すると、多くの設定ができます(here参照)。チャンネルの量(モノ、ステレオなど)、サンプルのサイズ(8ビット、16ビットなど)、レート(8000 Hz、16000 Hz、44100 Hzなど)を設定します。たとえば、これらのサンプルをPCMデバイスに書き込むには、snd_pcm_writeiと入力します。

ALSAライブラリの定義は、alsa/asoundlib.hにあります。 GCCを使用している場合は、-lasoundでALSAライブラリにリンクできます。

すべての音楽プレーヤーがこれらの低レベルのやりとりを使用するわけではありません。 ALSAの上に構築される多くのソフトウェアは、サウンドシステム(プラットフォームに依存しない)に対してより汎用的なインターフェースを提供します。サウンドサーバーの例には、JACKPulseAudioがあります。これらの健全なサーバーのメリットは、通常はセットアップと使用が簡単ですが、ALSAの細かい制御はできません。

+0

この関数を使用するには、ヘッダ 'alsa/asoundlib.h'を含めるべきですか?それともファイルですか?そして、ほとんどの音楽プレーヤーがどのように使用するのでしょうか? – Chromium

+0

@クロム私はいくつかの情報を追加しました。 – bzeaman

+0

そして 'pulseaudio'に言及して以来、それにはライブラリもありますか?あなたもその情報を提供できますか? – Chromium

2

LINUXがサウンド(あらゆる種類のmp3/wave /など)を再生するためには、ライブラリを使用することができます。 hereを参照してください。 ASLAプロジェクトでは多くのサウンドカードがサポートされています.WiKiでは、サウンドカードがサポートされているかどうかを確認する方法と、テストする方法のヒントを見ることができます。

あなたが処理する必要がある2つの別々の流れがあることを心に留めておくべきで新しいサウンドカード用のドライバを追加しようとしている場合:

  1. はHW(CODEC)を設定 - 通常これが行われますI2Cバスを使用して、h/wを設定します。たとえば、イコライザーの設定、モノ/ステレオの設定、アナログアンプの設定などがあります。
  2. データフロー - データは、linuxスタックからh/wへのファイルの実際のストリーミングです。あなたはストリーミングを処理するためにようにバッファを作成し、する必要がありますし、あなたはいくつかはすでにしようとする前に例が存在する参照することをお勧めしますので、これは非常に広大なフィールドです

/記録を開始/停止のためのALSA APIを使用してプレイできますあなた自身のドライバを書く。 ALSAコードに沿ってプリントを追加して、オーディオファイルの再生を開始するときに何が起きているのかを確認してください。

0
ここ

はその後、OpenALのを使用してレンダリングされたオーディオデータとメモリバッファに移入し、いくつかのCコードではありません - 音声ファイル

// sudo apt-get install libopenal-dev 
// 
// gcc -o gen_tone gen_tone.c -lopenal -lm 
// 

#include <stdio.h> 
#include <stdlib.h> // gives malloc 
#include <math.h> 


#ifdef __APPLE__ 
#include <OpenAL/al.h> 
#include <OpenAL/alc.h> 
#elif __linux 
#include <AL/al.h> 
#include <AL/alc.h> 
#endif 

ALCdevice * openal_output_device; 
ALCcontext * openal_output_context; 

ALuint internal_buffer; 
ALuint streaming_source[1]; 

int al_check_error(const char * given_label) { 

    ALenum al_error; 
    al_error = alGetError(); 

    if(AL_NO_ERROR != al_error) { 

     printf("ERROR - %s (%s)\n", alGetString(al_error), given_label); 
     return al_error; 
    } 
    return 0; 
} 

void MM_init_al() { 

    const char * defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); 

    openal_output_device = alcOpenDevice(defname); 
    openal_output_context = alcCreateContext(openal_output_device, NULL); 
    alcMakeContextCurrent(openal_output_context); 

    // setup buffer and source 

    alGenBuffers(1, & internal_buffer); 
    al_check_error("failed call to alGenBuffers"); 
} 

void MM_exit_al() { 

    ALenum errorCode = 0; 

    // Stop the sources 
    alSourceStopv(1, & streaming_source[0]);  //  streaming_source 
    int ii; 
    for (ii = 0; ii < 1; ++ii) { 
     alSourcei(streaming_source[ii], AL_BUFFER, 0); 
    } 
    // Clean-up 
    alDeleteSources(1, &streaming_source[0]); 
    alDeleteBuffers(16, &streaming_source[0]); 
    errorCode = alGetError(); 
    alcMakeContextCurrent(NULL); 
    errorCode = alGetError(); 
    alcDestroyContext(openal_output_context); 
    alcCloseDevice(openal_output_device); 
} 

void MM_render_one_buffer() { 

    /* Fill buffer with Sine-Wave */ 
    // float freq = 440.f; 
    float freq = 850.f; 
    float incr_freq = 0.1f; 

    int seconds = 4; 
    // unsigned sample_rate = 22050; 
    unsigned sample_rate = 44100; 
    double my_pi = 3.14159; 
    size_t buf_size = seconds * sample_rate; 

    short * samples = malloc(sizeof(short) * buf_size); 

    printf("\nhere is freq %f\n", freq); 
    int i=0; 
    for(; i<buf_size; ++i) { 
     samples[i] = 32760 * sin((2.f * my_pi * freq)/sample_rate * i); 

     freq += incr_freq; 
     // incr_freq += incr_freq; 
     // freq *= factor_freq; 

     if (100.0 > freq || freq > 5000.0) { 

      incr_freq *= -1.0f; 
     } 
    } 

    /* upload buffer to OpenAL */ 
    alBufferData(internal_buffer, AL_FORMAT_MONO16, samples, buf_size, sample_rate); 
    al_check_error("populating alBufferData"); 

    free(samples); 

    /* Set-up sound source and play buffer */ 
    // ALuint src = 0; 
    // alGenSources(1, &src); 
    // alSourcei(src, AL_BUFFER, internal_buffer); 
    alGenSources(1, & streaming_source[0]); 
    alSourcei(streaming_source[0], AL_BUFFER, internal_buffer); 
    // alSourcePlay(src); 
    alSourcePlay(streaming_source[0]); 

    // --------------------- 

    ALenum current_playing_state; 
    alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state); 
    al_check_error("alGetSourcei AL_SOURCE_STATE"); 

    while (AL_PLAYING == current_playing_state) { 

     printf("still playing ... so sleep\n"); 

     sleep(1); // should use a thread sleep NOT sleep() for a more responsive finish 

     alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state); 
     al_check_error("alGetSourcei AL_SOURCE_STATE"); 
    } 

    printf("end of playing\n"); 

    /* Dealloc OpenAL */ 
    MM_exit_al(); 

} // MM_render_one_buffer 

int main() { 

    MM_init_al(); 

    MM_render_one_buffer(); 
} 
関連する問題