PALMisLIFE 討論區

標題: 把 Treo 680 的 Voice Memo 由 PDB 轉換為 AMR [列印本頁]

作者: sun409    時間: 2009-6-10 11:20
標題: 把 Treo 680 的 Voice Memo 由 PDB 轉換為 AMR
先前不知道 Treo 680 的 Voice Memo 不能在 PC 上播放,
Palm 也沒有給同步的機制,
結果錄了一堆聲音都沒有辦法轉寄給親友!

參考網路上找到的 PDB format 寫了下面這段 C 程式,在 PC Linux 上使用 OK,
我已經把先前錄的全轉為 AMR 格式了,
AMR 要轉為 WAV 有免費的 Mobile AMR Converter
  1. #include <stdio.h>

  2. #define dmDBNameLength 32  /* 31 chars + 1 null terminator */

  3. #define PACKED __attribute__((packed))

  4. typedef unsigned char  UINT8;
  5. typedef unsigned short UINT16;
  6. typedef unsigned int   UINT32;

  7. typedef struct PACKED {
  8.    /* 8 bytes total */
  9.    UINT32 localChunkID;        /* offset to where record starts */
  10.    struct {
  11.        unsigned delete   : 1;
  12.        unsigned dirty    : 1;
  13.        unsigned busy     : 1;
  14.        unsigned secret   : 1;
  15.        unsigned category : 4;
  16.    } attributes;
  17.    UINT8 uniqueID[3];
  18. } RecordEntryType;

  19. typedef struct PACKED {
  20.    UINT32 nextRecordListID;
  21.    UINT16 numRecords;
  22. } RecordListType;

  23. typedef struct PACKED {
  24.    /* 78 bytes total */
  25.    UINT8          name[dmDBNameLength];
  26.    UINT16         attributes;
  27.    UINT16         version;
  28.    UINT32         createDate;
  29.    UINT32         modifyDate;
  30.    UINT32         lastBackupDate;
  31.    UINT32         modificationNumber;
  32.    UINT32         appInfoID;
  33.    UINT32         sortInfoID;
  34.    UINT8          type[4];
  35.    UINT8          creator[4];
  36.    UINT32         uniqueIdSeed;
  37.    RecordListType recordList;
  38. } pdb_header;

  39. typedef struct PACKED {
  40.    /* 8 bytes total */
  41.    UINT32 offset;
  42.    struct PACKED {
  43.        UINT32 delete   : 1;
  44.        UINT32 dirty    : 1;
  45.        UINT32 busy     : 1;
  46.        UINT32 secret   : 1;
  47.        UINT32 category : 4;
  48.    } attributes;
  49.    UINT8 uniqueID[3];
  50. } pdb_rec_header;

  51. typedef struct PACKED {
  52.    /* 8 bytes total */
  53.    UINT8 type[4];
  54.    UINT16 unknown;
  55.    UINT16 length;
  56. } pdb_rec_data_header;

  57. static UINT16 be2le16(UINT16 v)
  58. {
  59.    return ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8);
  60. }

  61. static UINT32 be2le32(UINT32 v)
  62. {
  63.    return ((v & 0x000000FF) << 24) | ((v & 0x0000FF00) << 8)
  64.           | ((v & 0x00FF0000) >> 8) | ((v & 0xFF000000) >> 24);
  65. }

  66. int main(int argc, char *argv[])
  67. {
  68.    if (argc != 3) {
  69.        printf("%s PDBname AMRname\n", argv[0]);
  70.        return 0;
  71.    }

  72.    FILE *fpi;

  73.    fpi = fopen(argv[1], "r");
  74.    if (NULL == fpi) {
  75.        printf("$s open failed\n", argv[1]);
  76.        return 0;
  77.    }

  78.    pdb_header h;
  79.    int size;

  80.    size = fread(&h, sizeof h, 1, fpi);
  81.    if (1 != size) {
  82.        printf("pdb header read error\n");
  83.        return 0;
  84.    }

  85.    printf("name:    %s\n", h.name);
  86.    printf("attr:    0x%04X\n", h.attributes);
  87.    printf("ver:     0x%04X\n", h.version);
  88.    printf("c_time:  0x%08X\n", h.createDate);
  89.    printf("m_time:  0x%08X\n", h.modifyDate);
  90.    printf("b_time:  0x%08X\n", h.lastBackupDate);
  91.    printf("mod no:  0x%08X\n", h.modificationNumber);
  92.    printf("appid:   0x%08X\n", h.appInfoID);
  93.    printf("sortid:  0x%08X\n", h.sortInfoID);
  94.    printf("type:    %c%c%c%c\n", h.type[0], h.type[1], h.type[2], h.type[3]);
  95.    printf("creator: %c%c%c%c\n", h.creator[0], h.creator[1], h.creator[2], h.creator[3]);
  96.    printf("id seed: 0x%08X\n", h.uniqueIdSeed);
  97.    printf("nextRec: 0x%08X\n", h.recordList.nextRecordListID);
  98.    printf("rec nos: 0x%04X\n", be2le16(h.recordList.numRecords));

  99.    int recs = be2le16(h.recordList.numRecords);
  100.    int i;
  101.    FILE *fpo;

  102.    fpo = fopen(argv[2], "w");
  103.    if (NULL == fpo) {
  104.        printf("$s open failed\n", argv[2]);
  105.        return 0;
  106.    }

  107.    for (i = 0; i < recs; i++) {
  108.        pdb_rec_header rh;

  109.        fseek(fpi, sizeof h + sizeof rh * i, SEEK_SET);

  110.        size = fread(&rh, sizeof rh, 1, fpi);
  111.        if (1 != size) {
  112.            printf("record head %d read error\n", i);
  113.            return 0;
  114.        }

  115.        printf("record %4d\n", i);
  116.        printf("    offset %d\n", be2le32(rh.offset));
  117.        printf("    delete   : %d\n", rh.attributes.delete);
  118.        printf("    dirty    : %d\n", rh.attributes.dirty);
  119.        printf("    busy     : %d\n", rh.attributes.busy);
  120.        printf("    secret   : %d\n", rh.attributes.secret);
  121.        printf("    category : %d\n", rh.attributes.category);
  122.        printf("    uniqueID : %02X%02X%02X\n", rh.uniqueID[0], rh.uniqueID[1], rh.uniqueID[2]);

  123.        pdb_rec_data_header rdh;

  124.        fseek(fpi, be2le32(rh.offset), SEEK_SET);

  125.        size = fread(&rdh, sizeof rdh, 1, fpi);
  126.        if (1 != size) {
  127.            printf("record data head %d read error\n", i);
  128.            return 0;
  129.        }
  130.        rdh.length = be2le16(rdh.length);

  131. #define BUF_SIZE 65536
  132.        /* For 16-bit value, the maximum is 65536 */
  133.        char buf[BUF_SIZE];

  134.        size = fread(buf, 1, rdh.length, fpi);
  135.        if (size != rdh.length) {
  136.            printf("record data read error, should be %d bytes\n", rdh.length);
  137.            return 0;
  138.        }
  139.        size = fwrite(buf, 1, rdh.length, fpo);
  140.        if (size != rdh.length) {
  141.            printf("record data write error\n");
  142.            return 0;
  143.        }
  144.    }

  145.    fclose(fpi);
  146.    fclose(fpo);

  147.    return 0;
  148. }
複製代碼

作者: james2mac    時間: 2009-8-10 16:55
可以提供.exe檔嗎?




歡迎光臨 PALMisLIFE 討論區 (http://f.pil.tw/) Powered by Discuz! X2.5