3535#include  < string> 
3636#include  < thread> 
3737#include  < vector> 
38+ #include  < sys/stat.h> //  For data_file_exists
39+ 
40+ #define  NDEBUG 
3841
3942#if  defined(WHISPER_BIG_ENDIAN)
4043template <typename  T>
@@ -979,6 +982,9 @@ struct whisper_context {
979982    whisper_state * state = nullptr ;
980983
981984    std::string path_model; //  populated by whisper_init_from_file_with_params()
985+ 
986+     std::string path_coreml; //  populated by whisper_init_from_file_with_params()
987+     std::string path_openvino; //  populated by whisper_init_from_file_with_params()
982988};
983989
984990struct  whisper_global  {
@@ -3341,9 +3347,56 @@ static std::vector<whisper_vocab::id> tokenize(const whisper_vocab & vocab, cons
33413347//  interface implementation
33423348// 
33433349
3350+ static  bool  data_file_exists  (const  char  * filename) {
3351+   struct  stat    buffer;   
3352+   return  (stat  (filename, &buffer) == 0 );
3353+ }
3354+ 
3355+ static  std::string replace_extra_data_directory (std::string path_bin, std::string replacement_path, bool  must_exist = true ) {
3356+     std::string new_path = replacement_path;
3357+     std::string file_part = path_bin;
3358+     
3359+     //  Check  replacement_path actually exists
3360+     if (must_exist && !data_file_exists (new_path.c_str ())) {
3361+         #ifdef  NDEBUG
3362+         fprintf (stderr, " Trying to replace with non-existant path %s returning passed path %s\n " c_str (), path_bin.c_str ());
3363+         #endif 
3364+         return  path_bin;
3365+     }
3366+     
3367+     //  Win 10/11 accepts both slashes while Linux/Mac only uses /
3368+     auto  pos = file_part.find_last_of (" /\\ " 
3369+     if  (pos != std::string::npos) {
3370+         file_part = file_part.substr (pos + 1 , std::string::npos);
3371+     }
3372+     
3373+ 
3374+     pos = new_path.find_last_of (" /\\ " 
3375+ 
3376+     //  Append trailing slash if required
3377+     if (pos < new_path.length () - 1 ) {
3378+     #ifdef  _WIN32
3379+       new_path = new_path + " \\ " 
3380+     #else 
3381+       new_path = new_path + " /" 
3382+     #endif 
3383+     }
3384+     
3385+     new_path = new_path + file_part;
3386+     
3387+     if (must_exist && !data_file_exists (new_path.c_str ())) {
3388+         #ifdef  NDEBUG
3389+         fprintf (stderr, " Error replacing path %s returning passed path %s\n " c_str (), path_bin.c_str ());
3390+         #endif 
3391+         return  path_bin;
3392+     }
3393+ 
3394+     return  new_path;
3395+ }
3396+ 
33443397#ifdef  WHISPER_USE_COREML
33453398//  replace .bin with -encoder.mlmodelc
3346- static  std::string whisper_get_coreml_path_encoder (std::string path_bin) {
3399+ static  std::string whisper_get_coreml_path_encoder (std::string path_bin, std::string path_coreml ) {
33473400    auto  pos = path_bin.rfind (' .' 
33483401    if  (pos != std::string::npos) {
33493402        path_bin = path_bin.substr (0 , pos);
@@ -3360,31 +3413,47 @@ static std::string whisper_get_coreml_path_encoder(std::string path_bin) {
33603413
33613414    path_bin += " -encoder.mlmodelc" 
33623415
3416+     if (!path_coreml.empty ()) {
3417+         path_bin = replace_extra_data_directory (path_bin, path_coreml);
3418+         fprintf (stderr, " Replacement CoreML path %s\n " c_str ());
3419+     }
3420+     
33633421    return  path_bin;
33643422}
33653423#endif 
33663424
33673425#ifdef  WHISPER_USE_OPENVINO
33683426//  replace .bin with-encoder-openvino.xml
3369- static  std::string whisper_openvino_get_path_encoder (std::string path_bin) {
3427+ static  std::string whisper_openvino_get_path_encoder (std::string path_bin, std::string path_openvino ) {
33703428    auto  pos = path_bin.rfind (' .' 
33713429    if  (pos != std::string::npos) {
33723430        path_bin = path_bin.substr (0 , pos);
33733431    }
33743432
33753433    path_bin += " -encoder-openvino.xml" 
33763434
3435+     if (!path_openvino.empty ()) {
3436+         path_bin = replace_extra_data_directory (path_bin, path_openvino);
3437+         fprintf (stderr, " Replacement OpenVINO path %s\n " c_str ());
3438+     }
3439+     
33773440    return  path_bin;
33783441}
33793442
3380- static  std::string whisper_openvino_get_path_cache (std::string path_bin) {
3443+ static  std::string whisper_openvino_get_path_cache (std::string path_bin, std::string path_openvino ) {
33813444    auto  pos = path_bin.rfind (' .' 
33823445    if  (pos != std::string::npos) {
33833446        path_bin = path_bin.substr (0 , pos);
33843447    }
33853448
33863449    path_bin += " -encoder-openvino-cache" 
33873450
3451+     if (!path_openvino.empty ()) {
3452+         //  This path doesn't have to exist as it may be created
3453+         path_bin = replace_extra_data_directory (path_bin, path_openvino, false );
3454+         fprintf (stderr, " Replacement OpenVINO cache path %s\n " c_str ());
3455+     }
3456+ 
33883457    return  path_bin;
33893458}
33903459#endif 
@@ -3456,20 +3525,22 @@ struct whisper_state * whisper_init_state(whisper_context * ctx) {
34563525    }
34573526
34583527#ifdef  WHISPER_USE_COREML
3459-     const  auto  path_coreml = whisper_get_coreml_path_encoder (ctx->path_model );
3528+     if (!ctx->params .disable_coreml ) {
3529+         const  auto  path_coreml = whisper_get_coreml_path_encoder (ctx->path_model , ctx->params .path_coreml );
34603530
3461-     WHISPER_LOG_INFO (" %s: loading Core ML model from '%s'\n " c_str ());
3462-     WHISPER_LOG_INFO (" %s: first run on a device may take a while ...\n " 
3531+          WHISPER_LOG_INFO (" %s: loading Core ML model from '%s'\n " c_str ());
3532+          WHISPER_LOG_INFO (" %s: first run on a device may take a while ...\n " 
34633533
3464-     state->ctx_coreml  = whisper_coreml_init (path_coreml.c_str ());
3465-     if  (!state->ctx_coreml ) {
3466-         WHISPER_LOG_ERROR (" %s: failed to load Core ML model from '%s'\n " c_str ());
3534+          state->ctx_coreml  = whisper_coreml_init (path_coreml.c_str ());
3535+          if  (!state->ctx_coreml ) {
3536+              WHISPER_LOG_ERROR (" %s: failed to load Core ML model from '%s'\n " c_str ());
34673537#ifndef  WHISPER_COREML_ALLOW_FALLBACK
3468-         whisper_free_state (state);
3469-         return  nullptr ;
3538+              whisper_free_state (state);
3539+              return  nullptr ;
34703540#endif 
3471-     } else  {
3472-         WHISPER_LOG_INFO (" %s: Core ML model loaded\n " 
3541+         } else  {
3542+             WHISPER_LOG_INFO (" %s: Core ML model loaded\n " 
3543+         }
34733544    }
34743545#endif 
34753546
@@ -3585,17 +3656,17 @@ int whisper_ctx_init_openvino_encoder_with_state(
35853656    std::string path_encoder;
35863657    if  (!model_path) {
35873658        // if model_path is not set, attempt to find it in the same directory as ggml-<model>.bin model
3588-         path_encoder = whisper_openvino_get_path_encoder (ctx->path_model );
3659+         path_encoder = whisper_openvino_get_path_encoder (ctx->path_model , ctx-> params . path_openvino );
35893660    } else  {
3590-         path_encoder = model_path;
3661+         path_encoder = replace_extra_data_directory ( model_path, ctx-> params . path_openvino ) ;
35913662    }
35923663
35933664    std::string path_cache;
35943665    if  (!cache_dir) {
35953666        // if cache_dir is not set, set it as a dir residing next to ggml-<model>.bin
3596-         path_cache = whisper_openvino_get_path_cache (ctx->path_model );
3667+         path_cache = whisper_openvino_get_path_cache (ctx->path_model , ctx-> params . path_openvino );
35973668    } else  {
3598-         path_cache = cache_dir;
3669+         path_cache = replace_extra_data_directory ( cache_dir, ctx-> params . path_openvino ) ;
35993670    }
36003671
36013672    WHISPER_LOG_INFO (" %s: loading OpenVINO model from '%s'\n " c_str ());
@@ -3634,11 +3705,17 @@ struct whisper_context_params whisper_context_default_params() {
36343705            /* .n_heads          =*/ 0 ,
36353706            /* .heads            =*/ NULL ,
36363707        },
3708+         /* .path_coreml          =*/ nullptr ,
3709+         /* .path_openvino        =*/ nullptr ,
3710+         /* .disable_coreml       =*/ false ,
36373711        /* .dtw_mem_size         =*/ 1024 *1024 *128 ,
36383712    };
36393713    return  result;
36403714}
36413715
3716+ //     std::string path_coreml; // populated by whisper_init_from_file_with_params()
3717+ //     std::string path_openvino; // populated by whisper_init_from_file_with_params()
3718+ 
36423719struct  whisper_context  * whisper_init_from_file_with_params_no_state (const  char  * path_model, struct  whisper_context_params  params) {
36433720    WHISPER_LOG_INFO (" %s: loading model from '%s'\n " 
36443721#ifdef  _MSC_VER
0 commit comments