Dim yByte() As Byte '音乐数据字节数组 ReDim yByte(my_wavData.nSize) 'my_wavData.nSize就是音乐数据的长度Open App.Path & "\123.wav" For Binary Access Read As #1 Open App.Path & "\456.wav" For Binary Access Write As #2 X$ = Input(44, #1) '文件头长度为44 Get #1, , yByte至此,如果这个WAV已知是16bit、双声道的,如何写入456.WAV,以提高音量?
最好不用控件,对WAV的数据按字节进行操作不行么?
Private Type WAVERIFF sID As String nSize As Long sType As String End TypePrivate Type WAVEdata sID As String nSize As Long dData As Byte End TypePrivate Type WAVEfact sID As String nSize As Long dData As Long End Type Private Type WAVEFORMAT nID As String nSize As Long '值为16或18,为18时则最后又附加信息 wFormatTag As Integer '编码方式 nChannels As Integer '声道1-单声道;2-双声道 nSamplesPerSec As Long '采样频率 nAvgBytesPerSec As Long '每秒字节数 nBlockAlign As Integer '数据块对齐单位(每个采样需要的字节数) nBitsPerSample As Integer '块调整值=声道数*采样位数/8 (注意数据类型,不是Long,微软的数据结构定义错了) nBitsPerSample1 As String '附加信息 End Type Dim my_wav As WAVEFORMAT Dim my_wavfact As WAVEfact Dim my_wavData As WAVEdata Dim my_wavRIFF As WAVERIFF Dim yByte() As Byte '音乐数据字节数组 Dim waveHDR(43) As BytePrivate Sub Form_Load() '导入的声音文件Fname Dim Fname As String Fname = App.Path & "\888.wav"Label3.Caption = "修改时间: " & FileDateTime(Fname) Label1.Caption = "文件: " & FnameOpen Fname For Binary Access Read As #1 Label2.Caption = "大小: " & LOF(1) & " 字节" Close #1 Open Fname For Binary Access Read As #1 Get #1, , waveHDR 'WAV文件的头部 Close #1
Open Fname For Binary Access Read As #1 '第一部分“RIFF” With my_wavRIFF .sID = Input(4, #1) '格式标志“RIFF”,4个字节 Get #1, , .nSize '文件长度LONG类型,大小等于WAV文件大小减去ID和Size所占用的字节 .sType = Input(4, #1) '“WAVE”,4个字节 End With
'第二部分“fmt ” With my_wav .nID = Input(4, #1) '“fmt ”,4个字节 Get #1, , .nSize 'size,值为16或18,为18时则最后又附加信息 Get #1, , .wFormatTag '编码方式 Get #1, , .nChannels '声道1-单声道;2-双声道 Get #1, , .nSamplesPerSec '采样率(单位:赫兹)典型值:11025、22050、44100、48000Hz Get #1, , .nAvgBytesPerSec '每秒字节数 Get #1, , .nBlockAlign '数据块对齐单位(每个采样需要的字节数)设定资料区所占的byte数 Get #1, , .nBitsPerSample '块调整值=声道数*采样位数/8 If .nSize = 18 Then .nBitsPerSample1 = Input(2, #1)
End WithLabel8 = my_wav.nID & " 声道:" & my_wav.nChannels & " 采样率:" & my_wav.nSamplesPerSec & _ " 每秒字节数:" & my_wav.nAvgBytesPerSec & " 每个采样点数:" & my_wav.nBitsPerSample '第三部分 With my_wavfact .sID = Input(4, #1) '标志"fact" If .sID = "data" Then GoTo dataA Get #1, , .nSize '数值为4 Get #1, , .dData End With dataA: '第四部分 With my_wavData If my_wavfact.sID = "data" Then my_wavfact.sID = "" .sID = "data" Get #1, , .nSize 'Get #1, , .dData '数据暂时不读取 End If End WithLabel4 = my_wavfact.sID & my_wavData.sID & "数据长度:" & my_wavData.nSize'以下是将相关数据处理后,写入999.WAV文件Open App.Path & "\999.wav" For Binary Access Write As #2 '打开目标文件 Put #2, 1, waveHDR '写入文件头部
If a(i) >= 32768 Then a(i) = a(i) * 1.5 Else a(i) = a(i) * 0.5 End If Put #2, ii, a(i) Next
Close #1 Close #2 End Sub 我的源程序是这样的,请大家看看。
1)你用 Beyond Compare 2 之类的工具二进制比较两个文件,除了声道数据部分其他是否相同。 2)16位数据是两个字节,a(i) 始终是一个字节,怎么想的? 3)For ii 的循环中 i 没变过,你一直处理始终不变的 a(i)? 4)Get #1, , a是从文件头之后开始读取, Put #2, ii, a(i)是从文件位置 45 开始写?
16位数据是两个字节
Dim q As Byte Dim b As ByteFor ii = 45 To my_wavData.nSize + 44 Get #1, , q 'Debug.Print q '对这个q 进行操作才有效,不过就是音质方面不是很饱满,放大的效果达到了 If q = 256 Then GoTo aaq Select Case q Case Is > 128 b = q * 0.6 Case Is < 128 b = q * 1.4 Case 128 b = q End Select
是这样么? Dim q As Integer Dim b As IntegerFor ii = 45 To my_wavData.nSize + 44 Get #1, , q 'Debug.Print q '对这个q 进行操作才有效,不过就是音质方面不是很饱满,放大的效果达到了 If q = 256 Then GoTo aaq Select Case q Case Is > 128 b = q * 0.6 Case Is < 128 b = q * 1.4 Case 128 b = q End Select
Dim q As Integer Dim b As Integer Dim lPosition As Long Dim lMax As Long Dim dScale As DoublelPosition = Seek(1) lMax = 0 For ii = 45 To my_wavData.nSize + 44 Get #1, , q lMax 为 Abs(q) 的最大值 Next dScale = 32767 / lMaxSeek #1, lPosition For ii = 45 To my_wavData.nSize + 44 Get #1, , q b 为 q 按 dScale 倍率放大 Put #2, ii, b Next
ReDim yByte(my_wavData.nSize) 'my_wavData.nSize就是音乐数据的长度Open App.Path & "\123.wav" For Binary Access Read As #1
Open App.Path & "\456.wav" For Binary Access Write As #2 X$ = Input(44, #1) '文件头长度为44
Get #1, , yByte至此,如果这个WAV已知是16bit、双声道的,如何写入456.WAV,以提高音量?
sID As String
nSize As Long
sType As String
End TypePrivate Type WAVEdata
sID As String
nSize As Long
dData As Byte
End TypePrivate Type WAVEfact
sID As String
nSize As Long
dData As Long
End Type
Private Type WAVEFORMAT
nID As String
nSize As Long '值为16或18,为18时则最后又附加信息
wFormatTag As Integer '编码方式
nChannels As Integer '声道1-单声道;2-双声道
nSamplesPerSec As Long '采样频率
nAvgBytesPerSec As Long '每秒字节数
nBlockAlign As Integer '数据块对齐单位(每个采样需要的字节数)
nBitsPerSample As Integer '块调整值=声道数*采样位数/8 (注意数据类型,不是Long,微软的数据结构定义错了)
nBitsPerSample1 As String '附加信息
End Type
Dim my_wav As WAVEFORMAT
Dim my_wavfact As WAVEfact
Dim my_wavData As WAVEdata
Dim my_wavRIFF As WAVERIFF
Dim yByte() As Byte '音乐数据字节数组
Dim waveHDR(43) As BytePrivate Sub Form_Load()
'导入的声音文件Fname
Dim Fname As String
Fname = App.Path & "\888.wav"Label3.Caption = "修改时间: " & FileDateTime(Fname)
Label1.Caption = "文件: " & FnameOpen Fname For Binary Access Read As #1
Label2.Caption = "大小: " & LOF(1) & " 字节"
Close #1
Open Fname For Binary Access Read As #1
Get #1, , waveHDR 'WAV文件的头部
Close #1
Open Fname For Binary Access Read As #1
'第一部分“RIFF”
With my_wavRIFF
.sID = Input(4, #1) '格式标志“RIFF”,4个字节
Get #1, , .nSize '文件长度LONG类型,大小等于WAV文件大小减去ID和Size所占用的字节
.sType = Input(4, #1) '“WAVE”,4个字节
End With
'第二部分“fmt ”
With my_wav
.nID = Input(4, #1) '“fmt ”,4个字节
Get #1, , .nSize 'size,值为16或18,为18时则最后又附加信息
Get #1, , .wFormatTag '编码方式
Get #1, , .nChannels '声道1-单声道;2-双声道
Get #1, , .nSamplesPerSec '采样率(单位:赫兹)典型值:11025、22050、44100、48000Hz
Get #1, , .nAvgBytesPerSec '每秒字节数
Get #1, , .nBlockAlign '数据块对齐单位(每个采样需要的字节数)设定资料区所占的byte数
Get #1, , .nBitsPerSample '块调整值=声道数*采样位数/8
If .nSize = 18 Then .nBitsPerSample1 = Input(2, #1)
End WithLabel8 = my_wav.nID & " 声道:" & my_wav.nChannels & " 采样率:" & my_wav.nSamplesPerSec & _
" 每秒字节数:" & my_wav.nAvgBytesPerSec & " 每个采样点数:" & my_wav.nBitsPerSample
'第三部分
With my_wavfact
.sID = Input(4, #1) '标志"fact"
If .sID = "data" Then GoTo dataA
Get #1, , .nSize '数值为4
Get #1, , .dData
End With
dataA: '第四部分
With my_wavData
If my_wavfact.sID = "data" Then
my_wavfact.sID = ""
.sID = "data"
Get #1, , .nSize
'Get #1, , .dData '数据暂时不读取
End If
End WithLabel4 = my_wavfact.sID & my_wavData.sID & "数据长度:" & my_wavData.nSize'以下是将相关数据处理后,写入999.WAV文件Open App.Path & "\999.wav" For Binary Access Write As #2 '打开目标文件
Put #2, 1, waveHDR '写入文件头部
Dim a() As Byte
Dim ii As Long
Dim b As Byte
ReDim a(my_wavData.nSize) '定义WAV文件的数据长度数组
Get #1, , a
For ii = 45 To my_wavData.nSize + 44
'音频数据以128(8位)或32768(16位)两个数为音频波形中线值
'我想将音量放大50%,就应该用下边的算法了
'可以写入后的文件没有一点声音
If a(i) >= 32768 Then
a(i) = a(i) * 1.5
Else
a(i) = a(i) * 0.5
End If
Put #2, ii, a(i)
Next
Close #1
Close #2
End Sub
我的源程序是这样的,请大家看看。
2)16位数据是两个字节,a(i) 始终是一个字节,怎么想的?
3)For ii 的循环中 i 没变过,你一直处理始终不变的 a(i)?
4)Get #1, , a是从文件头之后开始读取,
Put #2, ii, a(i)是从文件位置 45 开始写?
Dim q As Byte
Dim b As ByteFor ii = 45 To my_wavData.nSize + 44
Get #1, , q
'Debug.Print q
'对这个q 进行操作才有效,不过就是音质方面不是很饱满,放大的效果达到了
If q = 256 Then GoTo aaq
Select Case q
Case Is > 128
b = q * 0.6
Case Is < 128
b = q * 1.4
Case 128
b = q
End Select
aaq:
Put #2, ii, b音质方面还需要改进,请指教了。
&H1280 ( 4736) -> &H1980 ( 6528)
&H8080 (-32640) -> &H8080 (-32640)
&H7090 ( 28816) -> &H9D56 (-25258)
怎么不失真?
Dim q As Integer
Dim b As IntegerFor ii = 45 To my_wavData.nSize + 44
Get #1, , q
'Debug.Print q
'对这个q 进行操作才有效,不过就是音质方面不是很饱满,放大的效果达到了
If q = 256 Then GoTo aaq
Select Case q
Case Is > 128
b = q * 0.6
Case Is < 128
b = q * 1.4
Case 128
b = q
End Select
aaq:
Put #2, ii, b
next
放大比率 = 32767 / 现有振幅
然后用这个比率去放大波形。
否则波形的峰、谷可能会被切平。
Dim b As Integer
Dim lPosition As Long
Dim lMax As Long
Dim dScale As DoublelPosition = Seek(1)
lMax = 0
For ii = 45 To my_wavData.nSize + 44
Get #1, , q
lMax 为 Abs(q) 的最大值
Next
dScale = 32767 / lMaxSeek #1, lPosition
For ii = 45 To my_wavData.nSize + 44
Get #1, , q
b 为 q 按 dScale 倍率放大
Put #2, ii, b
Next
b 为 q 按 dScale 倍率放大
这个运行效率可能太低了,要是将这2个过程写出来就好了
method name : AmplifyPCMData
comment : 对PCM数据的音量进行放大
parameter :
pData PCM数据
nLen PCM数据的长度
nBitsPerSample 每个Sample的位数,一般为8的整数
multiple 放大倍数
result : S_OK 成功
---------------------------------------*/
int AmplifyPCMData(BYTE* pData, int nLen, int nBitsPerSample, float multiple)
{
int nCur = 0;
if (16 == nBitsPerSample)
{
while (nCur < nLen)
{
short* volum = (short*)(pData + nCur);
*volum = (*volum) * multiple;
if (*volum > SHRT_MAX)//爆音的处理
{
*volum = SHRT_MAX;
}
*(short*)(pData + nCur) = *volum ;
nCur += 2;
}
}
else if (8 == nBitsPerSample)
{
while (nCur < nLen)
{
BYTE* volum = pData + nCur;
*volum = (*volum) * multiple;
if (*volum > 255)//爆音的处理
{
*volum = 255;
}
*pData = *volum ;
nCur ++;
}
}
return S_OK;
}