CDには16bitのPCMの音声データが記録されているわけですが、それは一種の相対値であって再生時の絶対的な音量には任意性があります。それはCD再生機のボリュームつまみで音量を変えられることからわかります。
MPEGの音声圧縮のためには、心理音響解析が必要になりますが、そこには聴覚閾値が重要な要素としてからんできます。聴覚閾値を求めるには静音時の絶対聴覚閾値を定める必要がありますが、ここに不定性による困難が生じます。
更なる問題として、CDの音声データがCD毎に異なる規格化因子で記録されていることがあります。そのため再生装置の音量つまみを一定にしていても、CD毎に再生される音量が異なることになります。ラジオやテレビで流れるときに音が大きいほうが耳に残ってCMの効果があると考えられているため、近年のポップスCDでは全体の平均音量を上げることが習慣的に行われています。
一般的に、クラシック音楽や昔のポップスのデジタル・リマスターCDなどでは平均的な音量が小さく、最近のポップスでは平均的な音量が大きい傾向があります。
ここでは、それを定量的に見ることを考えて、手元に転がっていた種々のCDのPCMデータの平均値と標準偏差を調べます。将来、心理音響解析の聴覚閾値を求めるための、ヒントにすることを考えています。
以下の結果を見ると、聞いた感じの大体の傾向が結果に現れていることが見て取れます。
平均値3000、標準偏差10**7を超えるあたりからなんとなく耳障りになるように思います。
■実行結果
1カラム目はファイル名、2カラム目はPCMデータ数(左右の和)、3カラム目が16ビットPCMデータの整数値としての絶対値の平均、4カラム目はその標準偏差、5,6カラム目はそれぞれPCMデータの絶対値の最小および最大です。
◎クラシック曲
○古楽器による協奏曲
○古楽器室内楽編曲
○オーケストラ付き声楽曲
◎アナログ音源リマスター版
○サイモン・アンド・ガーファンクル
○マッシモ・ラニエリ、デオダート
○ジミー・スミス、オリバー・ネルソン
○マルコス・ヴァーリ
○カルロス・リラ
○マリア・トレド、ルイス・ボンファ
◎90年代初頭ポップス CD初期
○Betty Boo
○Jeremy Jordan
○Cathy Denis
○レニー・クラビッツ
http://www.amazon.com/build-this-garden-Single-CD/dp/B000M6TKPI
◎ポップス
○ジャミロ・クワイ
○Fatboy Slim
○デオダート (IRMAの糞デジタル化 音が荒い)
◎アニソン
○坂本真綾 Hatch Potch
○Cowboy Bebop OST1
○Leer Lied ローゼンメイデン
○涼宮ハルヒの詰合
○田村ゆかり True Romance
○松雪泰子 時を越えて
○大森玲子 ニャンダー仮面
ソース・コード
MODULE m_kind INTEGER, PARAMETER :: kd = SELECTED_REAL_KIND(10, 99) ! 10digits END MODULE m_kind !======================== MODULE m_wavio USE m_kind IMPLICIT NONE PRIVATE PUBLIC :: t_wavfile ! TYPE :: t_fmt SEQUENCE CHARACTER(4) :: chunk_id INTEGER(4) :: chunk_size INTEGER(2) :: format_id, channels INTEGER(4) :: sampling_rate INTEGER(4) :: bytes_per_sec INTEGER(2) :: block_size, bits_per_sample END TYPE t_fmt ! TYPE :: t_data SEQUENCE CHARACTER(4) :: chunk_id INTEGER(4) :: chunk_size ! pcm data END TYPE t_data ! TYPE :: t_riffwav SEQUENCE CHARACTER(4) :: chunk_id INTEGER(4) :: chunk_size CHARACTER(4) :: formattag TYPE (t_fmt ) :: fmt TYPE (t_data) :: dat END TYPE t_riffwav ! TYPE :: t_wavfile INTEGER :: unit = 10 INTEGER :: ipos CHARACTER(:), ALLOCATABLE :: fn TYPE (t_riffwav) :: riff CONTAINS PROCEDURE :: openfile PROCEDURE :: read_pcm_all PROCEDURE :: closefile ! FINAL :: close_file END TYPE t_wavfile CONTAINS !------------------------------------------------ SUBROUTINE openfile(this, fn) CLASS(t_wavfile), INTENT(IN OUT) :: this CHARACTER(*), INTENT(IN) :: fn INTEGER :: io this%fn = fn OPEN(this%unit, FILE = this%fn, ACCESS = 'STREAM', IOSTAT = io, STATUS = 'OLD', FORM = 'UNFORMATTED') IF (io /= 0) STOP 'end of file encountered' ASSOCIATE (riff => this%riff, fmt => this%riff%fmt, dat => this%riff%dat) ! RIFF-WAVE chunk READ(this%unit) riff IF (riff%chunk_id /= 'RIFF') STOP 'this is not RIFF file' IF (riff%formattag /= 'WAVE') STOP 'this RIFF file is not in WAVE format' ! fmt chunk IF ( fmt%chunk_id /= 'fmt ' ) STOP 'fmt chunk not found' IF ( fmt%format_id /= 1 ) STOP 'Unknown WAVE format' ! 1 Linear PCM IF ( fmt%bits_per_sample /= 16) STOP 'Not 16bit data' SELECT CASE ( fmt%channels ) CASE (1) ! WRITE(*, '(a, i3, a, i6, a)') 'Monoral', fmt%bits_per_sample, 'bit Sampling rate', fmt%sampling_rate, 'Hz ' CASE (2) ! WRITE(*, '(a, i3, a, i6, a)') 'Stereo' , fmt%bits_per_sample, 'bit Sampling rate', fmt%sampling_rate, 'Hz ' CASE DEFAULT STOP 'Wave channels must be 1 or 2' END SELECT ! data chunk IF (dat%chunk_id /= 'data') THEN DO INQUIRE(this%unit, POS = this%ipos) this%ipos = this%ipos + dat%chunk_size ! skip non-data chunk READ(this%unit, POS = this%ipos, IOSTAT = io) dat IF (io == -1) STOP 'end of file encounterd while searching for a data chunk' IF (dat%chunk_id == 'data') EXIT END DO END IF ! now POS is at the beginning of PCM data END ASSOCIATE RETURN END SUBROUTINE openfile !------------------------------------------------ SUBROUTINE closefile(this) CLASS(t_wavfile), INTENT(IN) :: this CLOSE(this%unit) RETURN END SUBROUTINE closefile !------------------------------------------------ SUBROUTINE read_pcm_all(this, pcm16) CLASS(t_wavfile), INTENT(IN) :: this INTEGER(2), ALLOCATABLE, INTENT(OUT) :: pcm16(:) ALLOCATE( pcm16( this%riff%dat%chunk_size / 2 ) ) READ(this%unit) pcm16 RETURN END SUBROUTINE read_pcm_all END MODULE m_wavio !============================================== PROGRAM test USE m_kind USE m_wavio IMPLICIT NONE TYPE (t_wavfile), ALLOCATABLE :: wavfile INTEGER(2), ALLOCATABLE :: pcm16(:) INTEGER :: i, j REAL :: ave, dev CHARACTER(256) :: fn ALLOCATE( wavfile ) PRINT *, 'Average sound intensity and standard deviation' DO i = 1, 99 WRITE(fn, '(a, i2.2, a)') 'Deodato_', i, '.wav' CALL wavfile%openfile(TRIM(fn)) CALL wavfile%read_pcm_all(pcm16) ave = SUM( ABS(REAL(INT(pcm16, 4))) ) / SIZE(pcm16) dev = SUM( (ABS(REAL(INT(pcm16, 4))) - ave)**2 ) / SIZE(pcm16) PRINT '(a, i10, a, f9.1, es12.2, 2i9)', TRIM(fn), SIZE(pcm16), ':', ave, dev, & MINVAL(ABS(INT(pcm16, 4))), MAXVAL(ABS(INT(pcm16, 4))) END DO DEALLOCATE( wavfile, pcm16 ) STOP END PROGRAM test