unity-调用讯飞星火语音唤醒-新版windowsSDK

调用讯飞星火语音唤醒-新版windowsSDK

先贴一张在unity中 wins系统下成功调用新版的讯飞windowsSDK的运行截图

调用成功为什么要用讯飞的语音唤醒?
项目中需要在unity和win系统下进行语音唤醒开启语音对话,而语音唤醒比较成熟的方案大多都是在linux系统下的,如snowboy,还有就是安卓系统的语音唤醒(各大厂都有)。win系统的就很少,我了解到的也只有讯飞有在做win系统的语音唤醒,如果从linux和安卓将语音唤醒功能移植到win下,不知道要花费多少时间。因此选择了讯飞

为什么要用这个新版的windowsSDK?

  1. 新版便宜。在官方费用上可以看到,旧版的低消为8000(最近618活动打折到了5600);而新版的低消为2500,打折后为1750
  2. 唤醒词设置方便。旧版需要在讯飞的官网上设置唤醒词,然后下载整个sdk,然后将sdk中的wakeupresource.jet文件替换,才能完成唤醒词的修改,并且如果你的语音唤醒过期了她还会提示你无法下载…;新版的sdk经过测试,将唤醒词以txt文本的方式写在了本地,也就意味着你直接在本地修改txt文件就可以完成唤醒词的修改,极大的减轻了开发人员的额外工作
  3. 与时俱进,新版肯定较旧版而言更有优势才会出新版

然而旧版的语音唤醒也还是有它的优势的

  1. 网上已经有很多调用旧版sdk的教程,跟着写就可以实现windowsSDK语音唤醒(是的我就是其中之一),无需将时间耗费在亲自写代码去调用dll中提供的api等各种繁琐而且有难度的事情上。官方的windowsSDK是dll的形式,如果不懂c++以及C#调用dll的代码的话,自己写会十分痛苦和消耗时间;新版的由于推出较晚,使用的人不多,网上相关的教程更是基本没有,问客服也是一问三不知,我手撸了差不多一个星期才实现了基本的调用。
  2. 旧版的语音唤醒和语音识别是连在一起的,唤醒搞定之后识别和合成等的的调用流程都是一样的,不需要太多额外的工作
  3. 新版的sdk中在c++环境下调用是否快速,但在dll调用中则困难重重

大家可以权衡利弊,选择合适自己项目的语音唤醒(讯飞原版及新版)

在讯飞官网中下载新版的源码后,可以在visual studio中试运行,看看体验如何,官方的demo中是提供了读取本地音频进行唤醒识别和实时通过麦克风接收到的数据进行唤醒识别两个选项

时间关系,先直接贴上调用成功的代码

public class MSCDLL : MonoBehaviour
{
    private const string _ability = "e867a88f2"; //这是默认的,请不要修改
    private const string _appID = "在官网上申请的应用的appid";
    private const string _apiSecret = "秘钥";
    private const string _apiKey = "key";
    private const string TAG = "MSCDLL";
    int _dll_result = 0;
    IntPtr _akikt_handle = IntPtr.Zero;
    // Start is called before the first frame update
    void Start()
    {
        byte[] bytes = ReadWavFile($"{Application.streamingAssetsPath}/output.wav");
        wakeup(bytes);//测试直接读取本地的音频,将其直接传给唤醒的api进行唤醒识别   
    }

    public void wakeup(byte[] bytes)
    {//卸载&释放语音唤醒sdk资源
        _dll_result = AIKIT_UnInit();
        Debug.Log($"{TAG}>>>AIKIT_UnInit>>>{(_dll_result == 0 ? "success" : "fail")}");

        //初始化并设置语音唤醒参数
        AIKIT_InitParam param = new AIKIT_InitParam();
        param.AppID = _appID;
        param.ApiSecret = _apiSecret;
        param.ApiKey = _apiKey;
        param.AuthType = 0;
        _dll_result = AIKIT_Init(param);
        Debug.Log($"{TAG}>>>AIKIT_InitParam>>>{(_dll_result == 0 ? "success" : "fail")}");

        //注册回调
        AIKIT_OnOutput onOutput = new AIKIT_OnOutput(OnOutput);
        AIKIT_OnEventDelegate onEvent = new AIKIT_OnEventDelegate(OnEvent);
        AIKIT_OnErrorDelegate onError = new AIKIT_OnErrorDelegate(OnError);
        AIKIT_Callbacks callbacks = new AIKIT_Callbacks
        {
            outputCB = onOutput,
            eventCB = onEvent,
            errorCB = onError
        };
        _dll_result = AIKIT_RegisterAbilityCallback(_ability, callbacks);
        Debug.Log($"{TAG}>>>AIKIT_RegisterAbilityCallback>>>{(_dll_result == 0 ? "success" : "fail")}");

        //初始化语音唤醒引擎
        AIKIT_BaseParam engintParam = null;
        int resutl2 = AIKIT_EngineInit(_ability, engintParam);
        Debug.Log($"{TAG}>>>AIKIT_EngineInit>>>{(_dll_result == 0 ? "success" : "fail")}");

        //加载唤醒所需要的资源参数>>>唤醒词文件路径
        string value = (Application.streamingAssetsPath + "\\xbxb.txt").Replace("/", "\\").Replace("\\", "\\\\");
        IntPtr tem = Marshal.StringToHGlobalAnsi(value);
        AIKIT_CustomData loadData = new AIKIT_CustomData("key_word", tem, 2);
        _dll_result = AIKIT_LoadData(_ability, loadData);
        Debug.Log($"{TAG}>>>AIKIT_LoadData>>>{(_dll_result == 0 ? "success" : "fail")}");

        //指定要使用的唤醒词文件数据集合,每次会话开启前需要调用。
        _dll_result = AIKIT_SpecifyDataSet(_ability, "key_word", new int[] { 0 }, 1);
        Debug.Log($"{TAG}>>>AIKIT_SpecifyDataSet>>>{(_dll_result == 0 ? "success" : "fail")}");
        //设置唤醒词文件的参数
        IntPtr aikit_handle_ptr = AIKITBuilder_Create(BuilderType.BUILDER_TYPE_PARAM);
        AIKITBuilderHandle aikit_param_handle = (AIKITBuilderHandle)Marshal.PtrToStructure(aikit_handle_ptr, typeof(AIKITBuilderHandle));
        _dll_result = AIKITBuilder_AddBool(aikit_param_handle, "gramLoad", true);//这一个字段不添加会报错无法运行
        //result = AIKITBuilder_AddString(aikit_handle, "wdec_param_nCmThreshold", "0 0:999", "0 0:999".Length);//这个可以不添加
        IntPtr param_ptr = AIKITBuilder_BuildParam(aikit_param_handle);
        AIKIT_BaseParam aikit_param = (AIKIT_BaseParam)Marshal.PtrToStructure(param_ptr, typeof(AIKIT_BaseParam));
        Debug.Log($"{TAG}>>>AIKITBuilder_BuildParam>>>{(_dll_result == 0 ? "success" : "fail")}");

        //开启唤醒>>>同时返回句柄,用于给>>>AIKIT_WRITE>>>当做参数调用,这个句柄包含了会话信息,如果不一致无法执行后面的write和end这两个函数
        _dll_result = AIKIT_Start(_ability, aikit_param, IntPtr.Zero, ref _akikt_handle);
        Debug.Log($"{TAG}>>>AIKIT_Start>>>{(_dll_result == 0 ? "success" : "fail")}>>>{_dll_result}");

        IntPtr aikit_data_handle_ptr = AIKITBuilder_Create(BuilderType.BUILDER_TYPE_DATA);
        AIKITBuilderHandle aikit_data_handle = (AIKITBuilderHandle)Marshal.PtrToStructure(aikit_data_handle_ptr, typeof(AIKITBuilderHandle));
        //将音频数据引到指定对象中,并传给dll
        BuilderData builderData = new BuilderData();
        builderData.type = (int)BuilderDataType.DATA_TYPE_AUDIO;
        builderData.name = "wav";
        builderData.status = 0;
        builderData.data = bytes;
        builderData.len = bytes.Length;
        _dll_result = AIKITBuilder_AddBuf(aikit_data_handle, builderData);
        Debug.Log($"{TAG}>>>AIKITBuilder_AddBuf>>>{(_dll_result == 0 ? "success" : "fail")}>>>{_dll_result}");

        //将数据对象传给dll后,调用dll的api获取根据数据对象生成的inputdata对象
        IntPtr data_ptr = AIKITBuilder_BuildData(aikit_data_handle);
        //将获取到的dataptr指针强转成我们需要的对象
        AIKIT_BaseData input_data = (AIKIT_BaseData)Marshal.PtrToStructure(data_ptr, typeof(AIKIT_BaseData));

        //将获取到的inputdata对象传入>>>AIKIT_Write>>>开始检测唤醒
        AIKIT_HANDLE aikit_handle = (AIKIT_HANDLE)Marshal.PtrToStructure(_akikt_handle, typeof(AIKIT_HANDLE));
        _dll_result = AIKIT_Write(aikit_handle, input_data);

        Debug.Log($"{TAG}>>>AIKIT_Write>>>{(_dll_result == 0 ? "success" : "fail")}>>>{_dll_result}");

        _dll_result = AIKIT_End(aikit_handle);
        Debug.Log($"{TAG}>>>AIKIT_End>>>{(_dll_result == 0 ? "success" : "fail")}>>>{_dll_result}");


    }
    // Update is called once per frame
    void Update()
    {

    }
    /// <summary>
    /// 卸载释放sdk
    /// </summary>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_UnInit();

    /// <summary>
    /// 初始化sdk
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_Init(AIKIT_InitParam data);
    /// <summary>
    /// 初始化引擎
    /// </summary>
    /// <param name="appid"></param>
    /// <param name="param"></param>
    /// <returns></returns>
    [DllImport("AEE_lib")]
    public static extern Int32 AIKIT_EngineInit(string appid, AIKIT_BaseParam param);
    /// <summary>
    /// 卸载释放引擎
    /// </summary>
    /// <param name="appid"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_EngineUnInit(string appid);
    /// <summary>
    /// 注册回调
    /// </summary>
    /// <param name="appid"></param>
    /// <param name="param"></param>
    /// <returns></returns>

    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_RegisterAbilityCallback(string appid, AIKIT_Callbacks param);

    /// <summary>
    /// 设置唤醒的参数
    /// </summary>
    /// <param name="appid"></param>
    /// <param name="param"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_LoadData(string appid, AIKIT_CustomData param);
    /// <summary>
    /// 设置唤醒词文件信息
    /// </summary>
    /// <param name="appid"></param>
    /// <param name="key"></param>
    /// <param name="index"></param>
    /// <param name="count"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_SpecifyDataSet(string appid, string key, int[] index, int count);

    /// <summary>
    /// 添加AIKITBuilderHandle对象
    /// </summary>
    /// <param name="builderType"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern IntPtr AIKITBuilder_Create(BuilderType builderType);
    /// <summary>
    /// 通过AIKITBuilderHandle对象设置bool类型的参数
    /// </summary>
    /// <param name="handle"></param>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKITBuilder_AddBool(AIKITBuilderHandle handle, string key, bool value);
    /// <summary>
    /// 通过AIKITBuilderHandle对象设置string类型的参数
    /// </summary>
    /// <param name="handle"></param>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <param name="len"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKITBuilder_AddString(AIKITBuilderHandle handle, string key, string value, int len);
    /// <summary>
    /// 通过AIKITBuilderHandle对象输入BuilderData对象,对象中记录字节数据
    /// </summary>
    /// <param name="handle"></param>
    /// <param name="builderData"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKITBuilder_AddBuf(AIKITBuilderHandle handle, BuilderData builderData);
    /// <summary>
    /// 通过AIKITBuilderHandle对象将刚才设置好的参数转成AIKIT_BaseParam对象
    /// </summary>
    /// <param name="handle"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern IntPtr AIKITBuilder_BuildParam(AIKITBuilderHandle handle);
    /// <summary>
    /// 通过AIKITBuilderHandle对象将刚才设置好的参数转成>>>AIKITBuilder_BuildData>>>对象
    /// </summary>
    /// <param name="handle"></param>
    /// <returns></returns>
    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern IntPtr AIKITBuilder_BuildData(AIKITBuilderHandle handle);
    /// <summary>
    /// 正式开启唤醒
    /// </summary>
    /// <param name="appid"></param>
    /// <param name="param"></param>
    /// <param name="userContext"></param>
    /// <param name="outHandle"></param>
    /// <returns></returns>

    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_Start(string appid, AIKIT_BaseParam param, IntPtr userContext, ref IntPtr outHandle);
    /// <summary>
    /// 传入需要唤醒检测的数据文件
    /// </summary>
    /// <param name="appid"></param>
    /// <param name="param"></param>
    /// <param name="userContext"></param>
    /// <param name="outHandle"></param>
    /// <returns></returns>

    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_Write(AIKIT_HANDLE handle, AIKIT_BaseData input);

    [DllImport("AEE_lib", CallingConvention = CallingConvention.StdCall)]
    public static extern Int32 AIKIT_End(AIKIT_HANDLE handle);

    public static byte[] ReadWavFile(string filePath)
    {
        // 确保文件存在
        if (!File.Exists(filePath))
        {
            Debug.Log(filePath);
            throw new FileNotFoundException("文件未找到", filePath);
        }

        // 读取文件的所有字节
        byte[] fileBytes = File.ReadAllBytes(filePath);
        return fileBytes;
    }

    private void OnOutput(IntPtr handle, AIKIT_BaseDataList output)
    {   // 处理输出回调
        //将Intprt转成aikitoutputdata,然后获取输出结果

        AIKIT_HANDLE output_handle = (AIKIT_HANDLE)Marshal.PtrToStructure(handle, typeof(AIKIT_HANDLE));
        Debug.Log(output_handle.abilityID);
        //AIKIT_BaseDataList input_data = (AIKIT_BaseDataList)Marshal.PtrToStructure(output, typeof(AIKIT_BaseDataList));
        Debug.Log("唤醒成功!");
    }
    private void OnEvent(IntPtr handle, int eventType, IntPtr eventValue)
    {   // 处理事件回调// 处理输出回调
        Debug.Log(eventValue);
    }
    private void OnError(IntPtr handle, int err, IntPtr desc)
    {   // 处理错误回调
        Debug.Log(desc);
    }
}
[StructLayout(LayoutKind.Sequential)]

public class AIKIT_InitParam
{
    public int AuthType;         // 授权方式,0=设备级授权,1=应用级授权  
    public string AppID;         // 应用id  
    public string ApiKey;        // 应用key  
    public string ApiSecret;     // 应用secret  
    public string WorkDir;       // sdk工作目录,需可读可写权限  
    public string ResDir;        // 只读资源存放目录,需可读权限  
    public string LicenseFile;   // 离线激活方式的授权文件存放路径,为空时需联网进行首次在线激活  
    public string BatchID;       // 授权批次  
    public string UDID;          // 用户自定义设备标识  
    public string CfgFile;       // 配置文件路径,包括文件名  
}
[StructLayout(LayoutKind.Sequential)]

public class AIKIT_BaseParam
{
    public IntPtr next; // 链表指针,使用IntPtr代替void*指针
    public IntPtr key; // 指针,使用IntPtr代替const char*
    public IntPtr value; // 指针,使用IntPtr代替void*
    public IntPtr reserved; // 预留字段,使用IntPtr代替void*
    public int len; // 数据长度
    public int type; // 变量类型
}
[StructLayout(LayoutKind.Sequential)]

public class AIKIT_CustomData
{
    public IntPtr Next;
    public byte[] KeyBytes;
    public IntPtr Value;
    public IntPtr Reserved;
    public int Index;
    public int Len;
    public int From;


    public AIKIT_CustomData(string key, IntPtr value, int from, int index = 0, int len = 0)
    {
        KeyBytes = Encoding.UTF8.GetBytes(key + "\0");
        Value = value;
        From = from;
        Index = index;
        Len = len;
        Reserved = IntPtr.Zero;
        Next = IntPtr.Zero;
    }

}
[StructLayout(LayoutKind.Sequential)]
public class AIKIT_HANDLE
{
    public IntPtr usrContext;
    public string abilityID;
    public IntPtr handleID;
}
[StructLayout(LayoutKind.Sequential)]
public class AIKITBuilderHandle
{
    public IntPtr builderInst;
    public BuilderType type;
}

public enum BuilderType
{
    BUILDER_TYPE_PARAM,
    BUILDER_TYPE_DATA
}
public enum BuilderDataType
{
    DATA_TYPE_TEXT,           // 文本
    DATA_TYPE_AUDIO,          // 音频
    DATA_TYPE_IMAGE,          // 图片
    DATA_TYPE_VIDEO           // 视频
}
[StructLayout(LayoutKind.Sequential)]
public class AIKIT_BaseData
{
    public IntPtr next; // 链表指针,使用IntPtr代替void*指针
    public AIKIT_BaseParam desc; // 指针,使用IntPtr代替const char*
    public string key;
    public IntPtr value; // 指针,使用IntPtr代替void*
    public IntPtr reserved; // 预留字段,使用IntPtr代替void*
    public int len; // 数据长度
    public int type; // 变量类型
    public int status; // 变量类型
    public int from; // 变量类型
}

[StructLayout(LayoutKind.Sequential)]
public class BuilderData
{
    public int type;    // 数据类型
    public string name; // 数据段名
    public byte[] data; // 数据段实体(当送入路径时,此处传入路径地址字符串指针即可;
    public int len;     // 数据段长度(当送入路径或文件句柄时,此处传0即可)
    public int status;  // 数据段状态,参考AIKIT_DataStatus枚举
}
// 定义委托类型
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void AIKIT_OnOutput(IntPtr handle, AIKIT_BaseDataList output);
public delegate void AIKIT_OnEventDelegate(IntPtr handle, int eventType, IntPtr eventValue);
public delegate void AIKIT_OnErrorDelegate(IntPtr handle, int err, IntPtr desc);

// 定义与C++结构体对应的C#结构体

// 定义与C++结构体对应的C#结构体
[StructLayout(LayoutKind.Sequential)]
public struct AIKIT_Callbacks
{
    public AIKIT_OnOutput outputCB;
    public AIKIT_OnEventDelegate eventCB;
    public AIKIT_OnErrorDelegate errorCB;
}



[StructLayout(LayoutKind.Sequential)]
public class AIKIT_BaseDataList
{
    public IntPtr node;
    //public AIKIT_BaseData node;
    public int count;
    public int totalLen;
}
  • 条件
    • 三个库文件
    • 一个唤醒词文件

先将官方的sdk中的三个库文件导入到unity中(项目assets文件夹中创建一个bin文件夹/放在plugins中),两个dll,一个lib
然后在项目中的某个路径下添加唤醒词文件(txt)
记得唤醒词文件的路径,在代码中需要获取那个文件
然后就可以直接运行测试了
我本地跑了很多次都是成功的,有问题可以留言

待解决的问题

  • 唤醒成功后的回调对象的转换还有问题
  • 哪些部分是初始化后不需要每次都调用的要和每次都需要调用的函数进行隔离
  • 代码整理,我将所有的逻辑都放在了一个类中,很不雅观

这次的代码之旅让我对指针和c++有了深刻的理解,在这几天的不断尝试中,我几度想放弃,网上关于sdk调用的知识很少,客服也是一问三不知,答非所问。不过还是坚持了下来…我可真是太棒了。
下班了就先写到这里了,有时间再把具体的实现流程补充一下吧
不过如果完整的看一遍下来,应该没什么问题,主要就是时间花在了读官方提供的demo源码以及自己根据源码中提供的api去模拟demo中的一些功能。
大概的情况就是,官方的demo源码中使用了很多工厂模式去新建对象,而在提供的dll中是没有这方面的函数的,刚官方的文档也是一点没写怎么不用工厂模式去新建对象。因此需要自己根据其他的函数,去模拟创建出工厂模式创建对象的过程。
当然看网上也有很多关于自己打dll包,将工厂模式之类没开放出来的函数开放出来,然后去调用那个自己打的dll包的说法,不过感觉目前我的能力还没有到那个水平就没有去尝试,有时间的话看看能不能摸索一下吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/731658.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue实现的商品列表网页

一、商品列表效果如下 二、代码&#xff1b; vue实现的商品列表网页 &#xff0c; 图片在vue项目的Public文件夹里的 imgs中 <template><div class"common-layout"><!-- el-container:外层容器。 当子元素中包含 <el-header> 或 <el-foo…

【性能优化】表分桶实践最佳案例

分桶背景 随着企业的数据不断增长&#xff0c;数据的分布和访问模式变得越来越复杂。我们前面介绍了如何通过对表进行分区来提高查询效率&#xff0c;但对于某些特定的查询模式&#xff0c;特别是需要频繁地进行数据联接查或取样的场景&#xff0c;仍然可能面临性能瓶颈。此外…

Vitis Accelerated Libraries 学习笔记--OpenCV 运行测试

目录 1. 简介 2. 实例测试 2.1 实例介绍 2.1 创建工程 3 常见错误 3.1 核心共享库报错 4. 总结 1. 简介 在《Vitis Accelerated Libraries 学习笔记--OpenCV 安装指南-CSDN博客》一文中&#xff0c;我详尽地介绍了 OpenCV 的安装过程。尽管 Vitis Vision 库的实现本身并…

泽众云真机-平台即将升级支持华为机型HarmonyOS NEXT系统

具小编了解&#xff0c;泽众云真机即将升级支持华为机型HarmonyOS NEXT系统。有些人可能对HarmonyOS NEXT系统了解不多。 之前我们有个银行项目&#xff0c;客户要求测试华为HarmonyOS NEXT系统环境&#xff0c;当时我们云真机尚未有该系统的机型&#xff0c;然后技术人员向华为…

企业智慧办公管理平台

摘要 在之前的疫情中&#xff0c;大多数企业都受到了较大的冲击&#xff0c;然而一些公司却因为工作的特殊性可以居家远程办公&#xff0c;不过这些企业在管理员工的过程中却遇到了较大的困难&#xff0c;这是因为这些企业的管理系统根本大多都无法管理员工的工作项目&#xf…

【面试干货】 Java 中的 HashSet 底层实现

【面试干货】 Java 中的 HashSet 底层实现 1、HashSet 的底层实现2、 HashSet 的特点3、 总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; HashSet 是 Java 集合框架中的一个重要成员&#xff0c;它提供了不存储重复元素的集合。但是&am…

【AI作曲】毁掉音乐?早该来了!一个网易音乐人对于 AI 大模型音乐创作的思辨

引言&#xff1a;AI在创造还是毁掉音乐&#xff1f; 正如当初 midjourney 和 StableDiffusion 在绘画圈掀起的风波一样&#xff0c;suno 和 各大音乐大模型的来临&#xff0c;其实早该来了。 AI 在毁掉绘画&#xff1f;或者毁掉音乐&#xff1f; 没错&#xff0c;但也错了。…

SuperImage高级免费版本下载,简单纯粹没有广告!

SuperImage是一款功能强大、易于使用的基于神经网络的图像放大工具&#xff0c;适用于各种场景&#xff0c;如修复老照片、增大图片尺寸、智能修复破损等。基于AI技术&#xff0c;使用MNN深度学习框架和Real-ESRGAN算法&#xff0c;能够提供高质量的图像处理效果。通过设备的GP…

嵌入式Linux驱动开研发流程详细解析

大家好,今天主要给大家分享一下,嵌入式linux中重要的内容详解。 一、驱动概念 驱动与底层硬件直接打交道,充当了硬件与应用软件中间的桥梁。 具体任务 读写设备寄存器(实现控制的方式) 完成设备的轮询、中断处理、DMA通信(CPU与外设通信的方式) 进行物理内存向虚拟内存…

综合评价 | 基于因子分析和聚类分析的节点重要度综合评价(Matlab)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 综合评价 | 基于因子分析和聚类分析的节点重要度综合评价&#xff08;Matlab&#xff09; 程序设计 完整程序和数据获取方式&#xff1a;私信博主回复基于因子分析和聚类分析的节点重要度综合评价&#xff08;Matlab…

Apache Arrow 和数据的未来:开放标准推动人工智能发展

Apache Arrow 是一种开源列式内存格式&#xff0c;适用于平面数据和分层数据。在现代数据湖中&#xff0c;开放数据格式&#xff08;如 Apache Arrow&#xff09;位于现代对象存储的存储层中。这些格式成为对象存储中的对象。 在最新版本中&#xff0c;Apache Arrow 宣布计划从…

碳钢酸洗线送酸槽蒸汽冷凝水PH计测量装置改进方法

碳钢酸洗线送酸槽蒸汽冷凝水PH计测量装置改进方法 一、项目提出前状况 1)立项背景 轧钢退火酸洗生产线的酸洗过程需要使用大量的硫酸、盐酸、硝酸、氢氟酸等酸液对钢带的表面进行清洗,酸洗过后产生较多的酸洗废水,酸洗废水需要经过处理达到污水排放标准后才能排放。其中酸…

蓝桥杯 经典算法题 实现归并排序

题目&#xff1a; 题解&#xff1a; 不断地将数组不断向下平均分为两部分&#xff0c;直到每个子数组中元素数量为1&#xff0c;这样就可以将相邻两个数组长度为1的数组看作是单调数组合并为一个大的单调数组&#xff0c;如此不断向上合并出最终的单调数组。 #include <bi…

百度地图3d区域掩膜,最常见通用的大屏地图展现形式

需求及效果 原本项目使用的是百度地图3.0,也就是2d版本的那个地图,客户不满意觉得不够好看,让把地图改成3d的,但是我们因为另外的系统用的都是百度地图,为了保持统一只能用百度地图做 经过3天的努力,最后我终于把这个效果实现了,效果如下: 如何引用GL版本 为了实现…

中国机器人产业崛起,德国市场面临30%的份额挑战

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 随着科技的不断进步&#xff0c;机器人行业正迎来前所未有的发展机遇。令人震惊的是&#xff0c;根据最新统计数据&#xff0c;中国机器人产业在…

蓝桥杯 经典算法题 求解完全背包问题

题目&#xff1a; 题解&#xff1a; 和01背包基本完全一样。小局部最优的策略也是一样&#xff1a;是否选当前局部的最后一项。唯一的不同点在于物品是无线的导致在表示选择当前物品的状态写法发生了改变&#xff1a;由dp[i-1][j-w[i]]变为了dp[i][j-w[i]]因为这样能够表示最后…

Android网络编程之Http通信

//使用HttpURLConnection打开连接 2.HttpURLConnection urlConn (HttpURLConnection) url.openConnection(); //得到读取的内容(流) 4.InputStreamReader in new InputStreamReader(urlConn.getInputStream()); // 为输出创建BufferedReader BufferedReader buffer new …

用户态协议栈04-定时arp-table的实现

之前有写过arp reply的实现&#xff0c;其中有写道&#xff0c;我们的系统内核中会维护一张ARP表&#xff0c;可以通过终端arp -a查看&#xff1a; 其中的dynamic和static是动态arp的类型&#xff0c;之前的udp实验就是添加了一条静态arp达到了发送的目的。在我们需要发送一个数…

android在线阅读代码网站

android在线阅读代码社区&#xff1a; Android 1.6 到 Android 10 的源码&#xff1a; Android OS 在线源代码 - https://www.androidos.net.cn10.0.0_r6 - Android社区 - https://www.androidos.net.cn/ AndroidXRef https://cs.android.com/ https://cs.android.com/android…

FFmpeg源码:AV_RB32宏定义分析

一、AV_RB32宏定义的作用 AV_RB32是FFmpeg源码中经常出现的一个宏&#xff0c;其定义如下&#xff1a; #ifndef AV_RB32 # define AV_RB32(p) AV_RB(32, p) #endif 该宏定义有多层。把它简化为函数&#xff0c;其函数声明可以等价于&#xff1a; uint32_t AV_RB32(uint…