libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmAudLabelFile.c 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmFloatTypes.h"
  4. #include "cmRpt.h"
  5. #include "cmErr.h"
  6. #include "cmCtx.h"
  7. #include "cmMem.h"
  8. #include "cmMallocDebug.h"
  9. #include "cmLinkedHeap.h"
  10. #include "cmFile.h"
  11. #include "cmAudLabelFile.h"
  12. cmAlfH_t cmAlfNullHandle = cmSTATIC_NULL_HANDLE;
  13. typedef struct cmAlfRecd_str
  14. {
  15. cmAlfLabel_t r;
  16. struct cmAlfRecd_str* link;
  17. } cmAlfRecd_t;
  18. typedef struct
  19. {
  20. cmErr_t err;
  21. cmLHeapH_t lH;
  22. cmFileH_t fH;
  23. cmAlfRecd_t* list;
  24. int cnt;
  25. } cmAlf_t;
  26. cmAlf_t* _cmAlfHandleToPtr( cmAlfH_t h )
  27. {
  28. cmAlf_t* p = (cmAlf_t*)h.h;
  29. assert( p != NULL );
  30. return p;
  31. }
  32. cmAlfRC_t _cmAlfFree( cmAlf_t* p )
  33. {
  34. cmAlfRC_t rc = kOkAlfRC;
  35. cmLHeapDestroy(&p->lH);
  36. cmMemPtrFree(&p);
  37. return rc;
  38. }
  39. cmAlfRC_t cmAudLabelFileAlloc( cmCtx_t* ctx, cmAlfH_t* hp )
  40. {
  41. cmAlfRC_t rc;
  42. if((rc = cmAudLabelFileFree(hp)) != kOkAlfRC )
  43. return rc;
  44. cmAlf_t* p = cmMemAllocZ(cmAlf_t,1);
  45. cmErrSetup(&p->err,&ctx->rpt,"Audio Label File");
  46. if(!cmLHeapIsValid( p->lH = cmLHeapCreate(1024,ctx)))
  47. {
  48. cmErrMsg(&p->err,kLHeapFailAlfRC,"Linked heap create failed.");
  49. goto errLabel;
  50. }
  51. hp->h = p;
  52. errLabel:
  53. return rc;
  54. }
  55. cmAlfRC_t cmAudLabelFileAllocOpen( cmCtx_t* ctx, cmAlfH_t* hp, const cmChar_t* fn )
  56. {
  57. cmAlfRC_t rc;
  58. if((rc = cmAudLabelFileAlloc(ctx,hp)) != kOkAlfRC)
  59. return rc;
  60. return cmAudLabelFileOpen(*hp,fn);
  61. }
  62. cmAlfRC_t cmAudLabelFileFree( cmAlfH_t* hp )
  63. {
  64. cmAlfRC_t rc = kOkAlfRC;
  65. if( hp == NULL || cmAudLabelFileIsValid(*hp)==false )
  66. return kOkAlfRC;
  67. cmAlf_t* p = _cmAlfHandleToPtr(*hp);
  68. if((rc = _cmAlfFree(p)) != kOkAlfRC )
  69. return rc;
  70. hp->h = NULL;
  71. return rc;
  72. }
  73. bool cmAudLabelFileIsValid( cmAlfH_t h )
  74. { return h.h != NULL; }
  75. void _cmAlfInsert( cmAlf_t* p, cmReal_t begSecs, cmReal_t endSecs, const cmChar_t* label )
  76. {
  77. cmAlfRecd_t* np = p->list;
  78. cmAlfRecd_t* pp = NULL;
  79. cmAlfRecd_t* ip = cmLhAllocZ(p->lH,cmAlfRecd_t,1);
  80. ip->r.begSecs = begSecs;
  81. ip->r.endSecs = endSecs;
  82. ip->r.label = label==NULL || strlen(label)==0 ? NULL : cmLhAllocStr(p->lH,label);
  83. // set np to the next recd and
  84. // set pp to the prev recd
  85. while(np != NULL )
  86. {
  87. if( np->r.begSecs > begSecs )
  88. break;
  89. pp = np;
  90. np = np->link;
  91. }
  92. ip->link = np;
  93. // if the new recd is first on the list
  94. if( pp == NULL )
  95. p->list = ip;
  96. else
  97. pp->link = ip;
  98. // incr the recd count
  99. ++p->cnt;
  100. }
  101. // remove the record just after pp
  102. void _cmAlfRemove( cmAlf_t* p, cmAlfRecd_t* pp )
  103. {
  104. // if the list is already empty
  105. if( p->list == NULL )
  106. return;
  107. // if the first recd should be removed
  108. if( pp == NULL )
  109. {
  110. p->list = p->list->link;
  111. }
  112. else
  113. {
  114. // if pp points to the last recd
  115. if( pp->link == NULL )
  116. return;
  117. // remove pp->link from the list
  118. pp->link = pp->link->link;
  119. }
  120. assert( p->cnt != 0 );
  121. --p->cnt;
  122. }
  123. cmAlfRC_t cmAudLabelFileOpen( cmAlfH_t h, const cmChar_t* fn )
  124. {
  125. cmAlfRC_t rc = kOkAlfRC;
  126. cmAlf_t* p = _cmAlfHandleToPtr(h);
  127. cmChar_t* lineBuf = NULL;
  128. unsigned lineBufByteCnt = 0;
  129. unsigned line = 1;
  130. cmFileH_t fH = cmFileNullHandle;
  131. // open the label file
  132. if( cmFileOpen(&fH,fn,kReadFileFl,p->err.rpt) != kOkFileRC )
  133. {
  134. rc = cmErrMsg(&p->err,kFileFailAlfRC,"The audio label file '%s' could not be openend.",cmStringNullGuard(fn));
  135. goto errLabel;
  136. }
  137. // read each line
  138. while( cmFileGetLineAuto(fH,&lineBuf,&lineBufByteCnt) == kOkFileRC )
  139. {
  140. cmReal_t begSecs;
  141. cmReal_t endSecs;
  142. cmChar_t* label = NULL;
  143. cmChar_t* begPtr = lineBuf;
  144. cmChar_t* endPtr = NULL;
  145. // parse the start time in seconds
  146. errno = 0;
  147. begSecs = strtod(begPtr,&endPtr);
  148. if( errno != 0 )
  149. return cmErrMsg(&p->err,kSyntaxErrAlfRC,"Begin time conversion error on line %i in '%s'.",line,cmFileName(fH));
  150. // parse the end time in seconds
  151. begPtr = endPtr;
  152. endSecs = strtod(begPtr,&endPtr);
  153. if( errno != 0 )
  154. return cmErrMsg(&p->err,kSyntaxErrAlfRC,"End time conversion error on line %i in '%s'.",line,cmFileName(fH));
  155. label = endPtr;
  156. // eat any leading white space off the label
  157. while( *label )
  158. {
  159. if( isspace(*label) )
  160. ++label;
  161. else
  162. break;
  163. }
  164. // trim trailing space and '\n' from the label.
  165. int i = strlen(label)-1;
  166. for(; i>=0; --i)
  167. {
  168. if( isspace(label[i]) )
  169. label[i]=0;
  170. else
  171. break;
  172. }
  173. // if the label does not exist
  174. if( strlen(label)==0 )
  175. label = NULL;
  176. // insert a new recd
  177. _cmAlfInsert(p,begSecs,endSecs,label);
  178. ++line;
  179. }
  180. cmMemPtrFree(&lineBuf);
  181. if( cmFileClose(&fH) != kOkFileRC )
  182. rc = cmErrMsg(&p->err,kFileFailAlfRC,"The audio label file close failed.");
  183. errLabel:
  184. return rc;
  185. }
  186. cmAlfRC_t cmAudLabelFileInsert( cmAlfH_t h, cmReal_t begSecs, cmReal_t endSecs, const cmChar_t* label )
  187. {
  188. cmAlfRC_t rc = kOkAlfRC;
  189. cmAlf_t* p = _cmAlfHandleToPtr(h);
  190. _cmAlfInsert(p,begSecs,endSecs,label);
  191. return rc;
  192. }
  193. unsigned cmAudLabelFileCount( cmAlfH_t h )
  194. {
  195. cmAlf_t* p = _cmAlfHandleToPtr(h);
  196. return p->cnt;
  197. }
  198. const cmAlfLabel_t* cmAudLabelFileLabel( cmAlfH_t h, unsigned idx )
  199. {
  200. cmAlf_t* p = _cmAlfHandleToPtr(h);
  201. cmAlfRecd_t* lp = p->list;
  202. unsigned i;
  203. for(i=0; lp!=NULL && i<idx; ++i)
  204. lp = lp->link;
  205. return &lp->r;
  206. }
  207. cmAlfRC_t cmAudLabelFileWrite( cmAlfH_t h, const cmChar_t* fn )
  208. {
  209. cmAlfRC_t rc = kOkAlfRC;
  210. cmAlf_t* p = _cmAlfHandleToPtr(h);
  211. cmAlfRecd_t* lp = p->list;
  212. cmFileH_t fH = cmFileNullHandle;
  213. if( cmFileOpen(&fH,fn,kWriteFileFl,p->err.rpt) != kOkFileRC )
  214. {
  215. rc = cmErrMsg(&p->err,kFileFailAlfRC,"The audio label output file '%s' could not be created.",cmStringNullGuard(fn));
  216. goto errLabel;
  217. }
  218. for(; lp!=NULL; lp=lp->link)
  219. {
  220. if( cmFilePrintf(fH,"%f %f %s",lp->r.begSecs,lp->r.endSecs,lp->r.label == NULL ? "" : lp->r.label) != kOkFileRC )
  221. {
  222. rc = cmErrMsg(&p->err,kFileFailAlfRC,"The audio label output file write failed.");
  223. goto errLabel;
  224. }
  225. }
  226. errLabel:
  227. if( cmFileClose(&fH) != kOkFileRC )
  228. {
  229. rc = cmErrMsg(&p->err,kFileFailAlfRC,"The audio label output file '%s' close failed.",cmStringNullGuard(fn));
  230. }
  231. return rc;
  232. }
  233. void cmAudLabelFileTest( cmCtx_t* ctx )
  234. {
  235. const cmChar_t* fn = "/home/kevin/temp/labels.txt";
  236. const cmChar_t* ofn = "/home/kevin/temp/labels_out.txt";
  237. cmAlfH_t h = cmAlfNullHandle;
  238. if( cmAudLabelFileAllocOpen(ctx,&h,fn) == kOkAlfRC )
  239. {
  240. unsigned n = cmAudLabelFileCount(h);
  241. unsigned i;
  242. for(i=0; i<n; ++i)
  243. {
  244. const cmAlfLabel_t* lp;
  245. if((lp = cmAudLabelFileLabel(h,i)) != NULL )
  246. cmRptPrintf(&ctx->rpt,"%f %f %s\n",lp->begSecs,lp->endSecs,lp->label);
  247. }
  248. cmAudLabelFileWrite(h,ofn);
  249. cmAudLabelFileFree(&h);
  250. }
  251. }