中文金额转换和语音播报(百度云)

这几天项目要实现一个播报类似于“XXX到账多少元”的功能,要我搞一个工具jar包。度娘上找了一些资料,定下一个大概思路:先将数字金额转换成中文金额,然后对其进行播报(最后效果感觉不如直接对数字进行播报,有兴趣的可以自己尝试一下,这个功能也可以用在其他地方)。

本文主要记录一下过程及最后结果,相关代码和链接也会填出来。

首先是中文金额转换,参考链接:https://github.com/zhao520a1a/NumToCN

原文中else if((numIndex - 2) % 4 == 0 && number % 1000 != 0 ) { //每隔4位,打印“圆,万,亿”

这里导致50000000输出为伍仟元,所以做了一点修改。

import java.math.BigDecimal;

public class NumToRMB {

    private static StringBuilder sb = new StringBuilder();

    private static final String[] CN_NUMBER = {"零", "壹", "贰", "叁", "肆", "伍", "六", "柒", "捌", "玖"};
    private static final String[] CN_UNIT  = { "分", "角", "圆","拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "兆", "拾", "佰", "仟", "顺" };

    private static final String CN_NEGATIVE = "负";
    private static final String CN_ZERO_FULL = "零圆";
    private static final int PERCISION = 2; // 精度

    public static String numToCn (BigDecimal numOfMoney) {

        //当此 BigDecimal 的值为负、零或正时,返回 -1、0 或 1。
        int signum = numOfMoney.signum();
        //若输入为0,输出零圆整;
        if(signum == 0) {
            return CN_ZERO_FULL;
        }
        //对金额进行四舍五入转化为long类型的整数;先将数的小数点向右移两位,然后在四舍五入,取绝对值,最后将它转换为长整型;
        long number = numOfMoney.movePointRight(PERCISION).setScale(0, BigDecimal.ROUND_HALF_UP).abs().longValue();
        int numIndex = 0; //记录数字的个数;
        boolean getZero = false;

        //得到小数部分(小数点后两位);
        long scale = number % 100;
        if(scale == 0) { //若小数部分为"00"时的情况;
            numIndex += 2;
            getZero = true;
            number /= 100;  // 从number去掉为0数;
        } else if(scale % 10 == 0){ //若小数部分为"*0"时的情况;
            numIndex += 1;
            getZero = true;
            number /= 10;// 从number去掉为0数;
        }
        //排除上述两种小数部分的特殊情况,则对小数和整数的处理就是一样的了
        while(true) {
            //循环结束条件;
            if(number <= 0){
                break;
            }

            //每次通过取余来得到最后一位数;
            int numUnit = (int)(number % 10);
            if(numUnit != 0){
                sb.insert(0, CN_UNIT[numIndex]);  //先添加单位
                sb.insert(0, CN_NUMBER[numUnit]); //在添加根据数字值来对应数组中的中文表述;
                getZero = false; //表明当前数不是0;
            }
            else {
                //它的上一次的数不是零,那么打印出零;
                if(!getZero) {
                    sb.insert(0, CN_NUMBER[numUnit]);
                }
                //若角分位为零,那么打印零;
                if(numIndex == 2) {
                    if(number > 0) {
                        sb.insert(0, CN_UNIT[numIndex]);
                    }
                } else if((numIndex - 2) % 4 == 0 && number / 1000 <= 9 ) { //每隔4位,打印“圆,万,亿”
                    sb.insert(0, CN_UNIT[numIndex]);
                }
                getZero = true; //将其置为true,那么如果下一位还是0,也不会再打印一遍'零';
            }

            // 从number每次都去掉最后一个数
            number  = number / 10;
            numIndex++;
        }
        // 如果signum == -1,则说明输入的数字为负数,就在最前面追加特殊字符:负
        if(signum == -1) {
            sb.insert(0, CN_NEGATIVE);
        }
        return sb.toString();
    }
}

语音播报参考:http://www.manongjc.com/article/60219.html

APPID、AK、SK都可在百度云开通相关功能后获取。

import com.baidu.aip.speech.AipSpeech;
import com.baidu.aip.speech.TtsResponse;
import com.baidu.aip.util.Util;
import javazoom.jl.player.Player;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;

/**
 * 将文本上传至百度服务器,返回语音文件,如output.mp3,并播放MP3文件
 * SDK下载地址:https://ai.baidu.com/file/EDF42F3DB3B4489FA1A88FD1E2BC5D74
 */
public class VoiceCompose {
    // 设置APPID/AK/SK
    // 百度AI开发平台的控制台中创建一个语音应用即可获得
    private static final String APP_ID = "25***66";
    private static final String API_KEY = "mT******3P";
    private static final String SECRET_KEY = "n********j";

    private static final AipSpeech aipSpeech = getAipSpeech();

    private static String filename = "output.mp3";

    private static Player player;

    private static AipSpeech getAipSpeech(){
        // 初始化一个AipSpeech
        AipSpeech aipSpeech = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);

        // 可选:设置网络连接参数
        aipSpeech.setConnectionTimeoutInMillis(2000);
        aipSpeech.setSocketTimeoutInMillis(60000);

        // 可选:设置代理服务器地址, http和socket二选一,或者均不设置
        //aipSpeech.setHttpProxy("proxy_host", proxy_port);  // 设置http代理
        //aipSpeech.setSocketProxy("proxy_host", proxy_port);  // 设置socket代理

        // 可选:设置log4j日志输出格式,若不设置,则使用默认配置
        // 也可以直接通过jvm启动参数设置此环境变量
        // System.setProperty("aip.log4j.conf", "path/to/your/log4j.properties");

        return aipSpeech;
    }

    /**
     * 将文字转为MP3文件,需联网,依靠百度语音合成
     * @param text
     * @return 是否成功
     */
    public boolean getMP3ByText(String text){
        player = null;

        // 设置可选参数
        HashMap<String, Object> options = new HashMap<>();
        // 语速,取值0-9,默认为5中语速
        options.put("spd", "3.6");
        // 音调,取值0-9,默认为5中语调
        options.put("pit", "5");
        // 音量,取值0-15,默认为5中音量
        options.put("vol", "12");
        // 发音人选择, 0为女声,1为男声,3为情感合成-度逍遥,4为情感合成-度丫丫,默认为普通女
        options.put("per", "0");

        // 调用接口
        // text 合成的文本,使用UTF-8编码。小于2048个中文字或者英文数字。(文本在百度服务器内转换为GBK后,长度必须小于4096字节)
        // lang 固定值zh。语言选择,目前只有中英文混合模式,填写固定值zh
        // ctp 客户端类型选择,web端填写固定值1
        TtsResponse res = aipSpeech.synthesis(text, "zh", 1, options);
        // 如果合成成功,下行数据为二进制语音文件,包含在data中。 如果合成出现错误,则会填充返回值到result中。
        // 若请求错误,服务器将返回的JSON文本包含以下参数:
        // error_code:错误码。
        // error_msg:错误描述信息,帮助理解和解决发生的错误。
        byte[] data = res.getData();
        JSONObject res1 = res.getResult();
        if (data != null) {
            try {
                Util.writeBytesToFileSystem(data, filename);
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }

        if (res1 != null) {
            System.out.println(res1.toString(2));
        }

        return true;
    }

    public void playMP3(){
        try {
            BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(filename));
            // 需导入javazoom.jl.player.Player,下载地址http://www.javazoom.net/javalayer/sources/jlayer1.0.1.zip
            player = new Player(buffer);
            player.play();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public String playerStatus(){
        if(player == null){
            return "null";
        }else if(player.isComplete()){
            return "played";
        }else{
            return "playing";
        }
    }
}

再附上Maven依赖:

    <dependencies>
        <dependency>
            <groupId>com.baidu.aip</groupId>
            <artifactId>java-sdk</artifactId>
            <version>4.12.0</version>
        </dependency>
        <dependency>
            <groupId>javazoom</groupId>
            <artifactId>jlayer</artifactId>
            <version>1.0.1</version>
        </dependency>
    </dependencies>

测试:

public class VoiceTest {
        public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);
        double money =  scan.nextDouble();
        BigDecimal numOfMoney = new BigDecimal(money);
        String s = NumToRMB.numToCn(numOfMoney);
        System.out.println(s);

        VoiceCompose voiceCompose = new VoiceCompose();
        String text = "系统到账" + s;
        if(!voiceCompose.getMP3ByText(text)){
            System.out.println("转换失败");
        }else{
            voiceCompose.playMP3();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值