Netwhale开发日志
原理
pcap
用来开发tcpdump的库,支持bpf语法,调用简单,其原理是从网卡那边复制了一份包的数据,而非截获,因此不能用libpcap实现注入,如果要这么做的话可以使用libnet(不过我记得api和文档不是很友好。)不过,这次的软件并不需要注入,只需要完成抓包的任务。
音高
音高(英语:pitch)在音乐领域里指的是人类心理对音符基频之感受。 –Wiki
参考的是以下2个说法
- 人类能分辨的两次声音之间需间隔0.1s以上
- 人耳的音高差别阈限(频率辨别阈或音调辨别阈),即辨别两个音的最小频率差需满足一定条件,1000Hz以下时为1~2Hz,在1000Hz以上时约为频率的0.1~0.2%。
据此,设计时需考虑音响设备支持的最高最低频率,以及人耳能够辨别的极限。以下为开发时参考的音高表。()
| 音名↓八度-> | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| C | 16.352(−48) | 32.703(−36) | 65.406(−24) | 130.81(−12) | 261.63(0) | 523.25(+12) | 1046.5(+24) | 2093.0(+36) | 4186.0(+48) | 8372.0(+60) | |
| C♯/D♭ | 17.324(−47) | 34.648(−35) | 69.296(−23) | 138.59(−11) | 277.18(+1) | 554.37(+13) | 1108.7(+25) | 2217.5(+37) | 4434.9(+49) | 8869.8(+61) | |
| D | 18.354(−46) | 36.708(−34) | 73.416(−22) | 146.83(−10) | 293.66(+2) | 587.33(+14) | 1174.7(+26) | 2349.3(+38) | 4698.6(+50) | 9397.3(+62) | |
| D♯/E♭ | 19.445(−45) | 38.891(−33) | 77.782(−21) | 155.56(−9) | 311.13(+3) | 622.25(+15) | 1244.5(+27) | 2489.0(+39) | 4978.0(+51) | 9956.1(+63) | |
| E | 20.602(−44) | 41.203(−32) | 82.407(−20) | 164.81(−8) | 329.63(+4) | 659.26(+16) | 1318.5(+28) | 2637.0(+40) | 5274.0(+52) | 10548(+64) | |
| F | 21.827(−43) | 43.654(−31) | 87.307(−19) | 174.61(−7) | 349.23(+5) | 698.46(+17) | 1396.9(+29) | 2793.8(+41) | 5587.7(+53) | 11175(+65) | |
| F♯/G♭ | 23.125(−42) | 46.249(−30) | 92.499(−18) | 185.00(−6) | 369.99(+6) | 739.99(+18) | 1480.0(+30) | 2960.0(+42) | 5919.9(+54) | 11840(+66) | |
| G | 24.500(−41) | 48.999(−29) | 97.999(−17) | 196.00(−5) | 392.00(+7) | 783.99(+19) | 1568.0(+31) | 3136.0(+43) | 6271.9(+55) | 12544(+67) | |
| G♯/A♭ | 25.957(−40) | 51.913(−28) | 103.83(−16) | 207.65(−4) | 415.30(+8) | 830.61(+20) | 1661.2(+32) | 3322.4(+44) | 6644.9(+56) | 13290(+68) | |
| A | 27.500(−39) | 55.000(−27) | 110.00(−15) | 220.00(−3) | 440.00(+9) | 880.00(+21) | 1760.0(+33) | 3520.0(+45) | 7040.0(+57) | 14080(+69) | |
| A♯/B♭ | 29.135(−38) | 58.270(−26) | 116.54(−14) | 233.08(−2) | 466.16(+10) | 932.33(+22) | 1864.7(+34) | 3729.3(+46) | 7458.6(+58) | 14917(+70) | |
| B | 30.868(−37) | 61.735(−25) | 123.47(−13) | 246.94(−1) | 493.88(+11) | 987.77(+23) | 1975.5(+35) | 3951.1(+47) | 7902.1(+59) | 15804(+71) |
结构
一图胜千言

代码和示例
代码放在github(https://github.com/Heersin/netwhale)上了,这边是一个小栗子,ping主机后获得的结果如下。
![[ping_AAC.mp4]] ## 开发遇到的问题 最主要的一个问题是开发过程中曾经出现播放5个单音后,产生segment fault,用gdb调试后发现问题出现在播放单音内的一个数组操作上,当时思考了如下原因:
- 数组读写时产生读写互斥的情况。之所以会考虑这个是由于前期调研中推荐libao的网友提到过libao在多线程程序中会有些奇奇怪怪的问题。由于libpcap中对包的处理采用异步操作,而通过查看libao的playaudio代码,其中device这个结构中存在一个swap空间,全局只有一个device,因此可以认为是一个全局静态变量,这个函数是不可重入的,推测是因为中断然后重入,造成数组的读写问题。
- 这边我在代码中加入了一个时延,留足libao调用设备播放的时间,看segment fault何时出现。结果依旧是5个单音后出现,gdb调试显示同样的结果。
- 数组用尽,堆增长过大?因为播放单音时,我在函数中使用的时calloc分配堆空间,首先检查自己是不是内存泄露了,发现在播放后并未进行free,尝试后爆出double free的错误,看来libao在播放中就释放了内存。接着用gdb查看map,在开辟buff的地方下断点,一步步跟踪,发现在第6个音时,需求的数组超过了堆标识。修改播放时间,能播的音变多了。
- 比对正常运行的程序,即使播放几十个音也不会产生该错误,百思不得其解。
- 数组越界?在进行第二步检查的时候发现,程序以16bit位的标准进行,比特位却设置为8,二者处理方式不一致导致数组发生越界。
后记
想着想着,最需要的功能应该是过滤一些层的声音,比如说网络层的东西就可以不要听,单听传输层,不然网络层声音过长了。此外声音有点尖锐,我想的一个解决方案是把数据映射到CC#DD#EFF#GG#AA#BB#这样一个范围内,或者其附件,具体的操作是每4位作为一个单音播放。每4位的好处在于可以以更细的粒度去用声音展现数据,以及数据范围在0-15,可以维持在正常的音高范围内。伪代码如下
// Define in header
#define A 440
#define A# 466
...(etc)
void playHalfByteA(u_char byte)
{
u_char half_byte = (byte>>4) & 0x0F;
playByte(half_byte);
}
void playHalfByteB(u_char byte)
{
u_char half_byte = byte & 0x0F;
playByte(half_byte);
}
这样分别播放前半字节和后半字节 ## 参考