标签 C 下的文章

1. 录音的 pcm 文件直接播放,使用:

#!/bin/bash
play -t raw -r 44.1k -e signed-integer -b 16 -c 2 loved.pcm
play -t raw -r 48k -e floating-point -b 32 -c 2 ./data_decode/out.pcm

参考: https://blog.csdn.net/lc999102/article/details/80579866

2. json.h 没有相应的头文件。json.h, curl.h

sudo apt-get install libjsoncpp-dev 
sudo ln -s /usr/include/jsoncpp/json/ /usr/include/json

sudo apt install libcurl4-openssl-dev
sudo ln -s /usr/include/x86_64-linux-gnu/curl /usr/include/curl

sudo apt-get install libopencv-dev

参考: https://blog.csdn.net/zhangpeterx/article/details/92175479

3. QCoreApplication 找不到定义的地方。

QCoreApplication 在 5.14.2/Src/qtbase/src/corelib/kernel/qcoreapplication.h 里面,定义为 class Q_CORE_EXPORT QCoreApplication。 参考: https://www.cnblogs.com/lyggqm/p/6281581.html

4. ffmpeg 的 cmake 配置

cmake_minimum_required(VERSION 3.10)

project(ffmpeg_test)

set(SRC_LIST main.cpp)
include_directories("/usr/include/x86_64-linux-gnu")
link_directories("/usr/lib/x86_64-linux-gnu")

add_executable(ffmpeg_test ${SRC_LIST})

#target_link_libraries(${PROJECT_NAME} libavutil.so libavcodec.so libavformat.so libavdevice.so.57 libavfilter.so libswscale.so libpostproc.so)

#target_link_libraries(${PROJECT_NAME} libavutil.so libavcodec.so libavformat.so libswscale.so)

target_link_libraries(${PROJECT_NAME} avutil avcodec avformat swscale)

参考: https://blog.csdn.net/wangchao1412/article/details/103454371 https://www.jianshu.com/p/72cdcb8d06a7 https://blog.csdn.net/BigDream123/article/details/89741253

5. 使用百度的 tts,需要安装百度 aip sdk

pip3 install baidu-aip --user

参考: https://blog.csdn.net/m0_37886429/article/details/85222593

6. pcm 和 wav 互转

参考: https://blog.csdn.net/sinat_37816910/article/details/105054372 https://blog.csdn.net/huplion/article/details/81260874

7. alsaaudio 中的 openPCM 这个参数的顺序有问题,不要按照 api 上面的顺序写。全部用关键词的方式去写,就没有问题。

        try:
            self.__alsaDev = alsaaudio.PCM(type = alsaaudio.PCM_PLAYBACK, mode = alsaaudio.PCM_NORMAL, rate = 16000, channels = 8, format = alsaaudio.PCM_FORMAT_S16_LE, periodsize = 160, device = "plughw:" + self.__devName)
        except Exception as e:
            print("alsaaudio open pcm exception: ", e)

8. 其他格式转换为 wav 格式,使用 pydub 中的 AudioSegment

    @staticmethod
    def extractToWave(srcPath, destDir = None, destPrefix = None):
        (srcDir, fileName) = os.path.split(srcPath)
        (fileNoExt, ext) = os.path.splitext(fileName)
        if ext == ".wav":
            return srcPath

        if destDir is None:
            destDir = srcDir
        if destPrefix is None:
            destPrefix = ""
        if not os.path.exists(destDir):
            os.makedirs(destDir)
        destName = destPrefix + fileNoExt + ".wav"
        destPath = destDir + "/" + destName
        #print(destPath)
        if ext == ".mp3":
            data = AudioSegment.from_mp3(srcPath)
        else:
            return None
        data.export(destPath, format = "wav")
        return destPath

参考: https://www.cnblogs.com/xingshansi/p/6799994.html https://ithelp.ithome.com.tw/articles/10252078 https://blog.csdn.net/baidu_29198395/article/details/86694365

9. alsaaudio 播放 wav 格式

    def playThreadWav(self, path, index):
        if self.__alsaDev:
            self.__alsaDev.close()
        print("alsa playback wav thread run: %d" % index)

        with wave.open(path, 'rb') as f:
            self.__rate = f.getframerate()
            self.__channels = f.getnchannels()
            self.__depthBits = f.getsampwidth() * 8
            self.__format = self.bitsToFormat(self.__depthBits)
            self.__periodSize = int(self.__rate / 100)
            try:
                self.__alsaDev = alsaaudio.PCM(type = alsaaudio.PCM_PLAYBACK,
                                               mode = alsaaudio.PCM_NORMAL,
                                               rate = self.__rate,
                                               channels = self.__channels,
                                               format = self.__format,
                                               periodsize = self.__periodSize,
                                               device = "plughw:" + self.__devName)
            except Exception as e:
                print("alsaaudio open exception: ", e)

            if self.__alsaDev is None:
                print("open alsa audio device failed")
                self.clearThreadParam(index)
                return "finished"

            data = f.readframes(self.__periodSize)
            while data and self.__eStop == False:
                try:
                    self.__alsaDev.write(data)
                except ALSAAudioError as e:
                    print("alsa audio play except: ", e)
                    break
                data = f.readframes(self.__periodSize)

        self.afterThreadComplete(index)
        return "finished"

    def clearThreadParam(self, index):
        del self.__poolDict[index]
        self.__rate = 0
        self.__channels = 0
        self.__depthBits = 0
        self.__format = 0
        self.__periodSize = 0

    def afterThreadComplete(self, index):
        self.__alsaDev.close()
        self.__alsaDev = None
        if index in self.__hookDict:
            if self.__eStop != True:
                self.__hookDict[index]()
            del self.__hookDict[index]
        self.clearThreadParam(index)

参考: https://www.programcreek.com/python/example/91453/alsaaudio.PCM

10. 使用 websocket 的时候, pip3 install --user websocket-client 而不是 websocket

11. pcm 转 wav

        (file, ext) = os.path.splitext(path)
        wavPath = file + ".wav"
        EspAudioUtil.pcmToWave(path, wavPath, rate, channels, bits)
        os.remove(path)

参考: https://stackoverflow.com/questions/16111038/how-to-convert-pcm-files-to-wav-files-scripting

12. 多通道音频抽取单通道数据

    @staticmethod
    def pcmExtractOneChannal(multiChannArray, channels, index):
        array = multiChannArray
        array.shape = -1, channels
        array = array.T
        return array[index]

    @staticmethod
    def pcmExtractOneChannalFile(multiPath, channels, index, dataBits, onePath):
        audioData = None
        if dataBits == 16:
            dataType = np.uint16
        with open(multiPath, 'rb') as f:
            audioData = np.fromfile(f, dtype = dataType)
        oneData = __class__.pcmExtractOneChannal(audioData, channels, index)
        oneData.tofile(onePath)

    @staticmethod
    def pcmExtractOneChannalBinary(multiBinary, channels, index, dataBits):
        audioData = None
        if dataBits == 16:
            dataType = np.uint16
        audioData = np.fromstring(multiBinary, dtype = dataType)
        oneData = __class__.pcmExtractOneChannal(audioData, channels, index)
        return oneData.tobytes()

参考: https://www.pythonf.cn/read/128012

13 pcm 和 wave 互转

    @staticmethod
    def pcmToWave(pcmPath, wavPath, rate, channels, depthBits):
        with open(pcmPath, "rb") as pcmFile:
            print("pcm open")
            pcmData = pcmFile.read()
        with wave.open(wavPath, "wb") as wavFile:
            print(channels, int(depthBits / 8), rate)
            print(len(pcmData))
            wavFile.setparams((channels, int(depthBits / 8), rate, 0, 'NONE', 'NONE'))
            wavFile.writeframes(pcmData)

    @staticmethod
    def waveToPCM(wavPath, pcmPath, dataBits = 16):
        if dataBits == 16:
            dataType = np.uint16
        with open(wavPath, 'rb') as f:
            f.seek(0)
            f.read(44)
            data = np.fromfile(f, dtype = dataType)
            data.tofile(pcmPath)
        with wave.open(wavPath, 'rb') as f:
            return f.getparams()

参考: https://blog.csdn.net/sinat_37816910/article/details/105054372 https://docs.python.org/3/library/wave.html

14. 停止 baidu 的 websocket,需要发送 cancel,至于是否 self.ws.keep_running = False 不太确定

参考: https://www.coder.work/article/1269314

15. 播放音乐并立即停止

cmd = "AUDIODEV=hw:realtekrt5651co play ~/esp_run/speech/test.wav"
sub = subprocess.Popen(cmd, shell = True)
print(sub.poll())
time.sleep(5)
print("kill")
print(time.time())
sub.kill()  #sub.send_signal(signal.SIGKILL)
# sub.wait()
print(time.time())
print(sub.poll())
sub = subprocess.Popen("stty echo", shell = True)

16. 如果需要使用 alsaaudio 在录音的时候播放其他音频,那么可能录音回发生 overrun,主要是播放音频的 set 函数回导致 overrun,其他一些耗时的处理也会导致 overrun,比如 mp3 解码。

17. subprocess kill 之后,使用 wait() 函数的时候,提示 EOFError 的时候,可以使用

stty sane

来恢复。

18. 寻找目录,寻找文件

def searchDir(path, dirName):
    for root, dirs, files in os.walk(path):
        if dirName in dirs:
            return os.path.join(root, dirName)
    return None

def searchFile(path, fileName):
    for root, dirs, files in os.walk(path):
        if fileName in files:
            return os.path.join(root, fileName)

19. 需要依赖的文件收集

def assembleDepends(path):
    cmd = 'grep -R "import" ' + path
    f = os.popen(cmd)
    data = f.readlines()
    f.close()
    #print(data)
    dependDict = {}
    if data != None:
        for line in data:
            lineData = line[line.find(":") + 1 : ]
            if lineData.startswith("#"):
                continue
            print(lineData)
            dependList = []
            if lineData.find("from") == -1:
                lineData = lineData.replace(" ", "").replace("\n", "")
                dependList = lineData[lineData.find("import") + len("import") : ].split(",")
                #print(dependList)
                for depend in dependList:
                    if depend.startswith("esp_"):
                        dependDict[depend] = 1
            else:
                start = lineData.find("from") + len("from") + 1
                end = lineData.find("import")
                lineData = lineData[start : end].strip()
                #print(lineData)
                if lineData.startswith("esp_"):
                    dependDict[lineData] = 1
        #print(dependDict)
        return dependDict
    return None

20. 降噪算法效果好,耗时低的是 WebRTC, python 可以使用 https://github.com/xiongyihui/python-webrtc-audio-processing 这边的代码。

转自:https://www.cnblogs.com/wzd5230/p/6744448.html

浮点型变量在计算机内存中占用4字节(Byte),即32-bit。

  遵循IEEE-754格式标准。 一个浮点数由2部分组成:底数m 和 指数e。

±mantissa × 2exponent (注意,公式中的mantissa 和 exponent使用二进制表示)

底数部分 使用2进制数来表示此浮点数的实际值。

指数部分 占用8-bit的二进制数,可表示数值范围为0-255。

         但是指数应可 正可负,所以IEEE规定,此处算出的次方须减去127才是真正的指数。所以float的指数可从 -126到128. 底数部分实际是占用24-bit的一个值,由于其最高位始终为 1 ,所以最高位省去不存储,在存储中只有23-bit。

  到目前为止, 底数部分 23位 加上指数部分 8位 使用了31位。那么前面说过,float是占用4个字节即32-bit,那么还有一位是干嘛用的呢? 还有一位,其实就是4字节中的最高位,用来指示浮点数的正负,当最高位是1时,为负数,最高位是0时,为正数。

  浮点数据就是按下表的格式存储在4个字节中:

Address+0 Address+1 Address+2 Address+3 Contents

SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM S: 表示浮点数正负,1为负数,0为正数

  E: 指数加上127后的值的二进制数

  M: 24-bit的底数(只存储23-bit)

      主意:这里有个特例,浮点数 为0时,指数和底数都为0,但此前的公式不成立。因为2的0次方为1,所以,0是个特例。当然,这个特例也不用认为去干扰,编译器会自动去识别。 通过上面的格式,我们下面举例看下-12.5在计算机中存储的具体数据:

Address+0 Address+1 Address+2 Address+3 Contents

0xC1 0x48 0x00 0x00 接下来我们验证下上面的数据表示的到底是不是-12.5,从而也看下它的转换过程。 由于浮点数不是以直接格式存储,他有几部分组成,所以要转换浮点数,首先要把各部分的值分离出来。

Address+0 Address+1 Address+2 Address+3

格式SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM

二进制 11000001 01001000 00000000 00000000

16进制 C1 48 00 00

可见:

S: 为1,是个负数。

E:为 10000010 转为10进制为130,130-127=3,即实际指数部分为3.

M:为 10010000000000000000000。

 这里,在底数左边省略存储了一个1,

使用 实际底数表示为1.10010000000000000000000 到此,我们吧三个部分的值都拎出来了,现在,我们通过指数部分E的值来调整底数部分M的值。调整方法为:如果指数E为负数,底数的小数点向左移,如果指数E为正数,底数的小数点向右移。小数点移动的位数由指数E的绝对值决定。 这里,E为正3,使用向右移3为即得: 1100.10000000000000000000 至次,这个结果就是12.5的二进制浮点数,将他换算成10进制数就看到12.5了,如何转换,看下面: 小数点左边的1100 表示为 (1 × 2^3) + (1 × 2^2) + (0 × 2^1) + (0 × 2^0), 其结果为 12 。 小数点右边的 .100… 表示为 (1 × 2^-1) + (0 × 2^-2) + (0 × 2^-3) + ... ,其结果为0.5 。 以上二值的和为12.5, 由于S 为1,使用为负数,即-12.5 。所以,16进制 0XC1480000 是浮点数 -12.5 。

今天在用codeblock打开几年前的avr工程,编译的时候,出错了,错误是 undefined reference to `eewr_byte_m169p。 经过1个小时的努力,终于找到问题所在了。 解释: As you see the EEPROM support has changed in recent years so that now the header files identify the AVR you are using (mega644) and then concatenate this onto the eewrbyte* style routine names and these are then provided in the link from the device specific .o file. When this works the map file shows something like: e:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5\libc.a(eewr_byte_atmega644.o) test.o (__eewr_byte_m644) That's built on Windows with WinAVR but the point is that it's ../avr/lib/avr5/libc.a that is providing the function. If you get undefined ref then that suggests that you environment is not linking with the right libc.a Maybe show your complete build output? Is the -mmcu=atmega644 being passed to the link as well as the compiles?

解决办法很简单,libc.a需要选择../avr/lib/avr5/libc.a这个才行。

今天被枚举给坑了一下,枚举不能用于预编译中间,不能就肯定不是想要的逻辑。 例如 enum{Name_0, Name_1, Name_2};

define NAME Name_2

int main(void) {

if (NAME == Name_1)

 printf("111\n");

else

printf("222\n");

endif

} 结果输出的肯定是 111

找到的解释如下

The `#if' command in its simplest form consists of

if expression controlled text #endif / expression /

The comment following the #endif' is not required, but it is a good practice because it helps people match the#endif' to the corresponding #if'. Such comments should always be used, except in short conditionals that are not nested. In fact, you can put anything at all after the#endif' and it will be ignored by the GNU C preprocessor, but only comments are acceptable in ANSI Standard C.

expression is a C expression of integer type, subject to stringent restrictions. It may contain

Integer constants, which are all regarded as long or unsigned long.

Character constants, which are interpreted according to the character set and conventions of the machine and operating system on which the preprocessor is running. The GNU C preprocessor uses the C data type `char' for these character constants; therefore, whether some character codes are negative is determined by the C compiler used to compile the preprocessor. If it treats `char' as signed, then character codes large enough to set the sign bit will be considered negative; otherwise, no character code is considered negative.

Arithmetic operators for addition, subtraction, multiplication, division, bitwise operations, shifts, comparisons, and `&&' and `||'.

Identifiers that are not macros, which are all treated as zero(!).

Macro calls. All macro calls in the expression are expanded before actual computation of the expression's value begins.

Note that `sizeof' operators and enum-type values are not allowed. enum-type values, like all other identifiers that are not taken as macro calls and expanded, are treated as zero.

The controlled text inside of a conditional can include preprocessor commands. Then the commands inside the conditional are obeyed only if that branch of the conditional succeeds. The text can also contain other conditional groups. However, the #if' and#endif' commands must balance.

From:

fork 作用是建立一个子进程,父子进程之间在fork()之后分道扬镳,子进程会获得一个父进程数据的副本。

在fork语句之前,printf有没有增加"\n"是非常重要的。如果没有"\n"那么printf的内容会写入显示缓冲,那么fork之后,子进程也会获得这个缓冲,所以如果在fork之前有printf,并且没有增加 "\n" 那么最后同样的内容,子进程和父进程会都打印一遍。

但是如果增加了 "\n" 就是立即显示了,那么子进程就不会有相应的显示缓冲,所以只会打印一遍.

最近做用430结果被BT定时器折腾了。BT定时器和以前接触过的AVR的普通定时器不太一样。以前的定时器都是计数到FF然后产生溢出中断。而BT定时器不一样。 MSP430 basic timer 基本定时器中断时间的计算 - ptz19861212 - ptz19861212的博客 BT定时器是在相应的选择位产生进位的情况下产生中断的。比如说,如果我们选中BTIPx为001的话,那么BTCNT2中的数据为 0x00,0x01,0x02,0x03然后在0X04的时候,也就是在Q1向Q2进位的时候产生中断。而且不管高位的数据,这个例子中Q3-Q7中的数据没有任何影响。

CC1101 在使用不定数据包长度的情况下,有一个需要注意的地方。当通讯不畅的时候,很可能长度字节接收出错,如果这时候,接收数组的长度不够的话,就会造成接收函数写入数组越界,所以在接收函数中需要加入对长度字节的判断,使得数组不会越界。