File size: 2,049 Bytes
92264aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e405f21
 
 
92264aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e405f21
92264aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**************************************************************************************************
 * ZipVoice AXERA C++ Port
 *
 * Vocoder: mel features → audio via vocos_full.axmodel + IRFFT + overlap-add.
 **************************************************************************************************/

#pragma once

#include <vector>
#include <string>
#include <memory>

#include "src/EngineWrapper.hpp"
#include "kiss_fft.h"

class Vocoder {
public:
    struct Config {
        std::string model_path;         // full model (or backbone in split mode)
        std::string head_model_path;    // head_linear model (optional, for split mode)
        const char* axclConfig = nullptr;
        int n_fft = 1024;
        int hop_length = 256;
        int n_mels = 100;
        int sample_rate = 24000;
    };

    Vocoder();
    ~Vocoder();

    /**
     * Initialize: load vocos_full.axmodel and pre-compute IRFFT basis.
     */
    int Init(const Config& cfg);

    /**
     * Decode mel features to audio waveform.
     * @param mel        Mel features [T, n_mels] (flat, row-major)
     * @param T          Number of mel frames
     * @param feat_scale Feature scaling factor to undo (Python: features/feat_scale before vocoder)
     * @param audio      Output audio samples (24kHz float32)
     */
    int Decode(const std::vector<float>& mel, int T, float feat_scale, std::vector<float>& audio);

    bool HasInit() const { return m_has_init; }

private:
    Config m_cfg;
    bool m_has_init;
    std::unique_ptr<EngineWrapper> m_session;
    std::unique_ptr<EngineWrapper> m_session_head;  // optional, for split mode

    // kissfft configs (shared forward/inverse twiddles)
    kiss_fft_state* m_fft_cfg = nullptr;
    kiss_fft_state* m_ifft_cfg = nullptr;

    // Hann window
    std::vector<float> m_window;

    // Window squared for envelope normalization
    std::vector<float> m_window_sq;

    int m_n_freqs;

    void BuildWindow();

    static void Fft(std::vector<float>& real, std::vector<float>& imag, bool inverse);
};