サりンドカヌドからの乱数。

倚くの人がこれたで乱数に興味を持っおいたす。 ほずんどすべおのコンピュヌタヌに組み蟌たれおいる「ハヌドりェアゞェネレヌタヌ」 、぀たりサりンドカヌドを䜿甚しお、真に乱数を取埗する実隓を共有したいず思いたす 。



玠材を準備する際に、叀いCコヌドをPythonで曞き盎したので、このopusは、暙準ctypesラむブラリを䜿甚しおPythonからWindows DLLを䜿甚する䟋でもありたす。



蚘事の最埌に、2枚のRealtekおよびAudigy 2サりンドカヌドから取埗したデヌタを比范し、統蚈的ランダムテストの結果を瀺したす。



UPD UFOが食べたコヌドのれロの欠萜を修正したした。



退屈な理論の玹介



ほずんどすべおのプログラミング蚀語は、いわゆる疑䌌乱数を生成するためのいく぀かの機胜を提䟛したす。 PSHは単語の数孊的な意味でランダムではなく、いく぀かのよく知られたアルゎリズムによっお取埗され、アルゎリズムの初期パラメヌタヌを知っおいるため、結果のシヌケンスは垞に再び繰り返されたす。 倚くのタスクで、高品質のPSCゞェネレヌタヌは真の乱数を完党に眮き換えるこずができたす。 コンピュヌタヌゲヌム、プロセスモデリング、モンテカルロ統合、遺䌝的アルゎリズム...優れたPSHで十分なタスクのリストは、長期間継続できたす。



䞀方、埗られたシヌケンスの真のランダム性が重芁である問題の限られたサヌクルがありたす。 䞻な䟋は暗号化です。 本圓に乱数を埗るこずに人々が垞に興味を持っおいたのは暗号化の文脈です。 最も単玔な䟋は、絶察暗号匷床が蚌明されおいる唯䞀の暗号です。Vernam暗号英語のワンタむムパッド は、キヌの秘密メッセヌゞず同じ長さの真に乱数のシヌケンスを必芁ずしたす。 暗号匷床を確保するために、キヌの生成に䜿甚されるランダムデヌタVernam暗号、AES、RSAなどを再利甚しないでください。 これは、信頌できる乱数の゜ヌスを芋぀けるずいう問題に぀ながりたす。



サりンドカヌドには、コンピュヌタヌの他のほずんどのコンポヌネントずは異なり、デゞタル郚分だけでなくアナログ郚分もありたす。



サりンドカヌドの線圢入力でオヌディオ信号をデゞタル化するプリミティブなプロセスを考えたす。

  1. 最初に、音に関する情報を䌝える䜕らかの゜ヌスからの電気信号がありたす
  2. 信号はサりンドカヌドのアナログ郚分に入り、そこで増幅されおADCアナログデゞタルコンバヌタヌのダむナミックレンゞに䞀臎したす。
  3. 信号は、特定の解像床ずサンプリング呚波数でADCによっおデゞタル化され、オヌディオカヌドのデゞタル郚分に入力されたす。この郚分からプログラムで取埗できたす。



パラグラフ2に興味がありたす。 ご存知のように、アナログ電気信号には必然的にノむズが含たれたす。ノむズ成分はいく぀かのカテゎリに倧別できたす。



干枉ずパワヌのランダム性が重芁なポむントである堎合、3番目のタむプのノむズは玔粋に量子であり、 真にランダムです。



実際問題は、このノむズがサりンドカヌドのデゞタル郚分にどれだけ浞透するかずいうこずです。 経隓によれば、それは浞透しおいたす。デゞタル化しお保存できたす。



16ビット蚘録モヌドでは、各サンプルの最䞋䜍ビットのみがランダム情報を䌝送したす.24ビットモヌドでは、いく぀かの最䞋䜍ビットが、垞に1぀の最䞋䜍ビットのみを取るこずが最も信頌できたす。 これをさらに行う方法ず、Windows甚のPythonプログラムの䟋を説明したす。



Pythonに興味がない人プログラムの説明の埌の最埌の結果ず結論の分析。




Windowsでの録音



Windowsでサりンドを録音する最も簡単な方法は、 winmm.dllラむブラリのWaveform Audioむンタヌフェむスを䜿甚するこずです。 Pythonでサりンドを操䜜するための暙準ラむブラリはないため、通垞のDLLぞのむンタヌフェむスを提䟛するctypesラむブラリを䜿甚したす 。



sysラむブラリ暙準出力ぞのアクセス甚ずtime  sleep関数ぞのアクセス甚をむンポヌトしたす。 たた、 ctypesからすべおの名前をむンポヌトしたす。



むンポヌトシステム

茞入 時間

ctypes むンポヌト から *




敎数通垞ぱラヌコヌドを返すC関数の堎合、Pythonでぱラヌコヌドをチェックする関数を指定できたす。 これを䜿甚しお、プログラムに最小限の゚ラヌ制埡を远加したす。C関数が゚ラヌを返す堎合、MMSYSERR_NOERRORはPython䟋倖をスロヌし、コン゜ヌルは問題がどこにあるかを正確に確認したす。



次に、リストからwinmm.dllラむブラリPythonオブゞェクトwindll.winmmがctypesからむンポヌトされたすの各関数に察しお、珟圚のvarsコンテキストで倉数を䜜成するルヌプがありたす。 .waveInOpen。 たた、戻り倀の型を「制埡」関数MMSYSERR_NOERRORに割り圓おたす。



def MMSYSERR_NOERROR 倀 

倀なら  = 0 

raise Exception  "winmm.dll関数の実行䞭の゚ラヌ" 、倀

戻り倀



[ "waveInOpen" 、 "waveInPrepareHeader"の funcnameの堎合、

"waveInAddBuffer" 、 "waveInStart" 、

"waveInStop" 、 "waveInReset" 、

"waveInUnprepareHeader" 、 "waveInClose" ] 

vars   [ funcname ] = windll。 winmm [ funcname ]

vars   [ funcname ] restype = MMSYSERR_NOERROR




Windows Audioで䜜業するために必芁なC構造を定矩したす。 構造クラスは、 ctypesからむンポヌトされた構造クラスを継承する必芁があり、構造芁玠の名前ずCタむプをリストする_fields_フィヌルドを含む必芁がありたす。 ctypesからCタむプのクラスをむンポヌトしたした。それらの名前は、c_int、c_uintなどを衚しおいたす。



最初のWAVEFORMATEX構造には、オヌディオデヌタ圢匏の情報が含たれおいたす。 パラメヌタヌがない堎合、コンストラクタヌはほずんどのサりンドカヌドの兞型的な倀である16ビット48 kHzモノラルの構造を䜜成したす。



2番目のWAVEHDRは、オヌディオデヌタのバッファヌを蚘述したす。 パラメヌタヌずしお、コンストラクタヌはWAVEFORMATEX型のオブゞェクトを必芁ずし、この圢匏の1秒の音声を保存できるバッファヌを割り圓おたす。 C文字の配列は、 create_string_buffer関数によっお䜜成されたす。



クラス WAVEFORMATEX 構造䜓 

WAVE_FORMAT_PCM = 1

_fields_ = [  "wFormatTag" 、c_ushort  、

 "nChannels" 、c_ushort  、

 "nSamplesPerSec" 、c_uint  、

 "nAvgBytesPerSec" 、c_uint  、

 "nBlockAlign" 、c_ushort  、

 "wBitsPerSample" 、c_ushort  、

 "cbSize" 、c_ushort  ]



def __init__  self 、samples = 48000 、bits = 16 、channels = 1  

自己 。 wFormatTag = WAVEFORMATEX 。 WAVE_FORMAT_PCM

自己 。 nSamplesPerSec =サンプル

自己 。 wBitsPerSample =ビット

自己 。 nChannels =チャンネル

自己 。 nBlockAlign = self nChannels * self 。 wBitsPerSample / 8

自己 。 nAvgBytesPerSec = self nBlockAlign * self 。 nSamplesPerSec

自己 。 cbSize = 0



クラス WAVEHDR 構造䜓 

_fields_ = [  "lpData" 、POINTER  c_char   、

 "dwBufferLength" 、c_uint  、

 "dwBytesRecorded" 、c_uint  、

 "dwUser" 、c_uint  、 ナヌザヌデヌタdwordたたはポむンタヌ

 "dwFlags" 、c_uint  、

 "dwLoops" 、c_uint  、

 "lpNext" 、c_uint  、 予玄枈みのポむンタヌ

 "reserved" 、c_uint  ] 予玄枈みのポむンタヌ

def __init__  self 、 Waveformat  

自己 。 dwBufferLength =波圢。 nAvgBytesPerSec

自己 。 lpData = create_string_buffer  ' \ 0 00' * self。dwBufferLength 

自己 。 dwFlags = 0




次に、waveFormatオブゞェクトを䜜成したす。 オヌディオデヌタ甚の3぀のバッファ。



残念ながら、ほずんどのドラむバヌでは、 winmm.dll かなり叀いむンタヌフェむスの可胜性がありたすでは、オヌディオカヌドがサポヌトしおいおも、16ビットをより正確にデゞタル化できたせん。 私は1枚のカヌドだけを知っおいたすSB Live24bit、それはできたした。 珟圚は手元にありたせんが、DirectXたたはASIOでのみ24ビットを曞き蟌むAudigy 2 Notebookがありたす。 したがっお、今日の䟋は16ビット甚に蚭蚈されおいたす24ビットで倉曎する必芁がある堎所は、カヌドがこれをサポヌトしおいる堎合にコメントでマヌクされおいたす。



waveFormat = WAVEFORMATEX サンプル= 48000 、ビット= 16 

waveBufferArray = [ 範囲  3 の iのWAVEHDR  waveFormat  ]




次の関数はプログラムの䞻芁な関数であり、 winmm.dllがバッファの1぀を満たしたずきにWindowsによっお呌び出されたす。



これはCコヌルバックであるため、最初にクラスを䜜成する必芁がありたす。 これはctypesのWINFUNCTYPE関数、匕数戻り倀の型、匕数の型によっお行われたす。 この関数は䜕も返すべきではないため、MSDNによるず、最初の匕数はNone 、残りはNoneです。 匕数POINTERc_uintに泚意しおください-これはナヌザヌデヌタぞのポむンタです。この䟋では単なる数字ですが、たずえば、デヌタを曞き蟌む堎所や必芁なデヌタ量を瀺すクラスなど、䜕でもかたいたせん。 POINTERWAVEHDRは、デヌタバッファヌぞのポむンタヌです。



uMsgパラメヌタヌは呌び出しの理由を瀺したす。MM_WIM_DATAに興味がありたす-オヌディオデヌタが利甚可胜です。



WRITECALLBACK = WINFUNCTYPE  None 、c_uint、c_uint、POINTER  c_uint  、POINTER  WAVEHDR  、c_uint 

def pythonWriteCallBack  HandleWaveIn、uMsg、dwInstance、dwParam1、dwParam2  

MM_WIM_CLOSE = 0x3BF

MM_WIM_DATA = 0x3C0

MM_WIM_OPEN = 0x3BE

uMsg == MM_WIM_OPENの堎合 

"Open handle =" 、HandleWaveInを印刷したす

elif uMsg == MM_WIM_CLOSE

"Close handle =" 、HandleWaveInを印刷し たす

elif uMsg == MM_WIM_DATA

#print "Data handle ="、HandleWaveIn

wavBuf = dwParam1。 内容

wavBufの堎合 。 dwBytesRecorded > 0 

bits = [ ord  wavBuf。lpData [ i ]   1 for i in range  0 、 wavBuf。dwBytesRecorded 、 2  ]

24ビットの堎合前の行の2の終わりを3に眮き換えたす

範囲 = 0 、 len ビット 、 2 の iのバむアス= [ビット[ i ] 、ビット[ i ]の 堎合  =ビット[ i + 1 ] ]

bytes = [ chr  reduce  lambda v、bv << 1 | b、bias [ i- 8 i ] 、 0   i for range  8 、 len  bias  、 8  ]

rndstr = '' 。 結合  バむト 

#print bytes、

sys 暙準 曞き蟌み  rndstr 

wavBufの堎合 。 dwBytesRecorded == wavBuf。 dwBufferLength 

waveInAddBuffer  HandleWaveIn、dwParam1、sizeof  waveBuf  

その他 

「1぀のバッファの解攟」 、dwInstance [ 0 ]を出力したす

dwInstance [ 0 ] -= 1

その他 

「䞍明なメッセヌゞ」を発生させる




キヌポむント

bits = [ ord  wavBuf。lpData [ i ]   1 for i in range  0 、 wavBuf。dwBytesRecorded 、 2  ]


デヌタは2バむト24ビットの堎合は3バむトでパックされるため、2のステップで配列を調べたす範囲0、wavBuf.dwBytesRecorded、2。ペアの最䞋䜍バむトの最䞋䜍ビットを遞択したす ordwavBuf.lpData [i] 1 。 結果は、各サンプルの最䞋䜍ビットのビットのリストです。



小さな数孊的な䜙談


ランダムデヌタは異なる分垃を持぀堎合がありたす。 特定の番号の発生頻床。 たずえば、ビット0000100000000のシヌケンスがあり、ナニットの䜍眮がランダムに倉化する堎合、これもランダムシヌケンスですが、れロが発生する確率がナニットよりもはるかに高いこずは明らかです。 最も䟿利ないわゆる れロず1の発生確率が等しい「均䞀分垃」 。 均䞀な分垃に還元する手順は、バむアスなしず呌ばれたす。 最も簡単な方法は眮換です10-> 1、01-> 0、11-> discard、00-> discard



バむアスを解陀するず、次の行が実行されたす

範囲 = 0 、 len ビット 、 2 の iのバむアス= [ビット[ i ] 、ビット[ i ]の 堎合  =ビット[ i + 1 ] ]


ステップ2を実行したす range0、lenbits、2 、同じペアを投げたす  bits [i]= Bits [i + 1] 、残りから最初に取るビット[i]。



最埌に、この匏はビットをバむトに収集し、すべおを文字列にマヌゞしたす

bytes = [ chr  reduce  lambda v、bv << 1 | b、bias [ i- 8 i ] 、 0   i for range  8 、 len  bias  、 8  ]


8ビットごずに、 reduce関数が呌び出されたすラムダv、bv << 1 | b、バむアス[i-8i]、0 。 ここでは、関数型プログラミング芁玠、匿名関数䞀時的にFず呌びたしょう lambda v、bv << 1 | bを䜿甚したす。次のようなreduce関数によっお呌び出されたす。バむアス[i-7]、...、バむアス[i-1]- chr関数によっお文字に倉換されるバむトが刀明したす。



バむトのリストはstdoutに曞き蟌たれる文字列に倉換されたす。これは、このバむナリデヌタの方が出力をファむルにリダむレクトする方がよいためです。 コン゜ヌルに曞き蟌む堎合、コン゜ヌルぞのバむナリ出力時にWindowsがCtrl + Cを適切にキャッチしないため、 「 print bytes 」を䜿甚しおこれを行うこずをお勧めしたす。



関数の最埌には、バッファが完党に満たされおいるかどうかを確認するチェックがありたす。 そうである堎合、システムに戻しおwaveInAddBuffer関数で埋めたす。 そうでない堎合、これはデヌタ出力が停止しおいるデバむスが閉じおいるこずを意味し、占有バッファのカりンタヌを1぀枛らしたすカりンタヌはナヌザヌデヌタに保存されたす。



pythonWriteCallBack関数からWRITECALLBACKクラスのC関数のむンスタンスを䜜成したす。



次に、いく぀かの䟿利な定数を定矩した埌、最初にWAVE_FORMAT_QUERYパラメヌタヌでフォヌマットがサポヌトされおいるこずを確認し、次にCALLBACK_FUNCTIONパラメヌタヌで、WAVE_MAPPERデバむスを開きたすサりンドカヌド番号を盎接蚭定できたす。ナヌザヌデヌタこの䟋では、ExitFlagの数。



byref関数を䜿甚しお、ポむンタヌがPythonからC関数にどのように枡されるかに泚目しおください 。 たた、 byrefExitFlagで「ナヌザヌデヌタ」ぞのポむンタヌを枡したした。Windowsは、むベントごずにdwInstanceの圢匏でコヌルバックに枡したすたずえば、バッファヌを埋める。



次に、䜜成された各バッファヌに察しおwaveInPrepareHeaderを呌び出し、waveInAddBufferを䜿甚しおwinmm.dllを枡したす。 最埌に、waveInStartHandleWaveInを呌び出すず、音声の入力を開始するように指瀺されたす。 サむクルtime.sleep1で埅っおいる終わり。



キヌの組み合わせCtrl + CPython KeyboardInterrupt をむンタヌセプトしお、プログラムを終了したす。

writeCallBack = WRITECALLBACK  pythonWriteCallBack 

詊しおください 

ExitFlag = c_uint  3 

HandleWaveIn = c_uint  0 

WAVE_MAPPER = c_int  -1 

WAVE_FORMAT_QUERY = c_int  1 

CALLBACK_FUNCTION = c_int  0x30000 



waveInOpen  0 、WAVE_MAPPER、byref  waveFormat  、 0、0 、WAVE_FORMAT_QUERY 

waveInOpen  byref  HandleWaveIn  、WAVE_MAPPER、byref  waveFormat  、writeCallBack、byref  ExitFlag  、CALLBACK_FUNCTION 



waveBufferArrayのwaveBufの堎合

waveInPrepareHeader  HandleWaveIn、byref  waveBuf  、sizeof  waveBuf  

waveInAddBuffer  HandleWaveIn、byref  waveBuf  、sizeof  waveBuf  



waveInStart  HandleWaveIn 



䞀方 1

時間 。 寝る  1 



KeyboardInterrupt を陀く 

waveInReset  HandleWaveIn 



䞀方 1

時間 。 寝る  1 

ExitFlagの堎合 。 倀 == 0 

ç Žã‚‹



waveBufferArrayのwaveBufの堎合

waveInUnprepareHeader  HandleWaveIn、byref  waveBuf  、sizeof  waveBuf  



waveInClose  HandleWaveIn 




行末の自動倉換を無効にするには、「- u 」パラメヌタヌを䜿甚しおスクリプトを呌び出す必芁がありたす。

c:\...\python.exe -u .py > .rnd







結論





倖郚信号なしで録音するこずができ、「無音」だけで、䞋䜍ビットはランダムな倀を取埗したす。 倖郚信号゜ヌスなしで録音するず、オヌディオカヌドの回路に自然に存圚するノむズの特性が埗られたす。 別のオプションずしお、䜕らかの信号を蚘録するず、最䞋䜍ビットのデゞタル化゚ラヌにノむズが珟れる堎合がありたす。



垞にデゞタル化゚ラヌがありたすが、䞀方で、「れロ」ノむズはオヌディオカヌドの物理デバむスに倧きく䟝存しおおり、䞀郚のモデルでは衚瀺されない堎合がありたす。 「れロ」ノむズの分析結果に぀いおは、以䞋で説明したす。



実隓的に埗られた録音のための最適なミキサヌ蚭定録音チャンネルを遞択したす再生ではありたせん Line-In 、チャンネルの音量を最倧にし、他のチャンネルをすべおオフにしたす。



倚くのオヌディオカヌドがマむクからの信号を「改善」し、さたざたなデゞタルフィルタヌを適甚しようずしおいるため、マむクチャネルは乱数の品質が最悪です。 テストされたオヌディオカヌドの1぀぀たりRealtek で、マむクチャネルはミッドレンゞの受信に適さない出力を生成したした。 Audigy 2では 、Mic Boost + 20DBAマむクゲむンをオンにするず、ランダムなコンポヌネントも削陀されたした。



いく぀かのプログラムを䜿甚しお、受信した乱数の品質をテストできたす。 最も䜿いやすいent http://www.fourmilab.ch/random/random.zipからダりンロヌド。 コン゜ヌルから実行

> type data.rnd | ent.exe





data.rndがランダムデヌタを含むバむナリファむルである堎合プログラム内の䜙分な印刷をコメントアりトするこずを忘れないでください。統蚈を少し損なう可胜性がありたす。 テストに最適なファむルサむズは玄です。 500KB プログラムはいく぀かのパラメヌタヌをカりントしたす。





ランダム性の基準は本質的に統蚈的であり、シヌケンス自䜓ではなく、゜ヌスに適甚されるこずに泚意しおください。 したがっお、信頌できる結果を埗るには、1぀の゜ヌスのサンプルに察しお䞀連のテストを実斜する必芁がありたす。 たずえば、500KBの20個。 倧倚数がテストに合栌した堎合玄90、゜ヌスは䞀定の確率でランダムです。



残念ながら、統蚈には100の基準はありたせん。 䞀定の確率で、サりンドカヌドがこの蚘事を生成できたす実際、これが私が埗た方法です-冗談です。



たた、NIST米囜芏栌協䌚のより掗緎された゜フトりェアパッケヌゞを䜿甚しお、䞡方のサりンドカヌドの「れロ」出力のランダム性をテストしたした。 䞡方のカヌドは良質の乱数を瀺したした。



興味深いこずに、 Realtekの内蔵オヌディオは、明らかにADCの品質が䜎くノむズが高いため、分垃の均䞀性がわずかに向䞊しおいたす。 Audigy 2はRealtekでサポヌトされおいない24ビットモヌドでは競合したせんいずれにしおも、DirectXが必芁であり、PythonのDirectXは別の話です。



他のテストパッケヌゞぞのリンク

http://stat.fsu.edu/pub/diehard/

http://www.phy.duke.edu/~rgb/General/dieharder.php

http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html



Audigy 2ラむン入力から無音を蚘録するこずにより取埗したファむルでのentプログラム出力の䟋

Entropy = 7.999609 bits per byte.



Optimum compression would reduce the size

of this 500000 byte file by 0 percent.



Chi square distribution for 500000 samples is 270.78, and randomly

would exceed this value 23.75 percent of the times.



Arithmetic mean value of data bytes is 127.5890 (127.5 = random).

Monte Carlo value for Pi is 3.139644559 (error 0.06 percent).

Serial correlation coefficient is 0.001109 (totally uncorrelated = 0.0).







All Articles