2010-07-24 7 views
4

Comme petit morceau de musique expérimentale, j'essaie de programmer un morceau en C standard. Le code génère un fichier PCM brut qui peut être importé dans Audacity. À l'heure actuelle, tout fonctionne comme prévu, mais je rencontre des problèmes lorsque j'essaie d'écrire chaque échantillon en 16 bits par opposition à l'actuel 8 bits que j'utilise. Jusqu'à l'écriture, l'échantillon courant est calculé comme un flottant et ses limites sont maintenues à peu près dans la plage d'un entier signé de 8 bits. Il est ensuite écrit comme un entier de 8 bits avant de répéter le processus pour l'échantillon suivant. Cela fonctionne bien et joue correctement. Le problème se produit lorsque j'essaie de l'écrire en tant que fichier PCM brut 16 bits - je multiplie le flottant par 256 et copiez le résultat dans un entier, sur quoi j'utilise fwrite pour écrire l'entier 16 bits résultant. Cela ne donne pas les résultats attendus lors de l'importation, ce qui entraîne une version très déformée de ce que j'attendais.Problème lors de l'écriture d'un fichier PCM brut 16 bits

J'ai ajouté le code valide ci-dessous, car le problème se produit uniquement à l'écriture.

travail Code 8bit:

if (out<-127) {out=-128;} else if (out>126) {out=127;} 
putc(out,fo); 

ne fonctionne pas Code 16bit:

if (out<-127) {out=-128;} else if (out>126) {out=127;} 
pcm=out*256; 
fwrite(&pcm,2,1,fo); 

Je suis probablement manque quelque chose d'évident, mais je l'ai essayé de travailler dehors Pendant des heures. Merci d'avance!

+0

est pcm un int16_t? – RWS

+0

Hm ... Je pensais que les fichiers WAV 8 bits étaient supposés utiliser des échantillons * non signés *. –

+0

Vous devez afficher la déclaration de 'pcm'. – caf

Répondre

3

J'imagine que regarder la forme d'onde dans Audacity vous aurait donné quelques indices.

Avez-vous vérifié:

  • le boutisme est correct?
  • que vous n'êtes pas censé utiliser, par ex. entiers non signés?
  • vous avez correctement marqué le fichier en 16 bits?

Je ne sais pas quel est le format attendu pour PCM, mais ce sont tous des candidats probables pour le problème.

+0

S'il écrit un fichier PCM brut, il n'y aura pas d'en-tête de format de fichier (donc votre 3ème point n'est probablement pas nécessaire). L'OP devra choisir le format (tel que mono/stéréo, taux d'échantillonnage, largeur de bit par échantillon, etc.) lors de l'importation dans Audacity. – stakx

+0

les bits, signés/non signés et endianness (essayé tous les types) sont sélectionnés lors de l'importation. – blkrbt

+0

@blkrbt: Êtes-vous capable de synthétiser des formes d'ondes arbitraires? Pouvez-vous générer une onde sinusoïdale à pleine échelle et regarder la forme d'onde dans Audacity, pour voir si elle est coupée/encapsulée/autre chose? –

0

Il est recommandé de faire des conversions de type lors des conversions. Par exemple, si sur est un flotteur, puis

putc((int) out, fo); 

laissera le compilateur savoir que vous voulez écrire votre numéro comme un entier.

Bien sûr, le compilateur le comprendra de toute façon pour quelque chose comme putc, mais cela ne fonctionne pas pour le référencement. Si vous déclarez la variable pcm comme flottante, alors fwrite écrira des données à virgule flottante au lieu de ce que vous voulez. Donc, je vais poser la même question: est pcm un type entier?

Une autre question est: avez-vous vraiment besoin de virgule flottante ici? Vous pourriez en avoir besoin si vous pouvez utiliser la précision décimale (encore une fois, vous perdrez cette précision en affichant un format 8 bits ou 16 bits), mais c'est un gâchis si vous ne faites que des calculs simples avec vos échantillons. Par conséquent, vous pouvez simplifier beaucoup les choses en vous en tenant à un type entier, et en le convertissant en char/int8_t lorsque vous écrivez.

+0

pcm est un nombre entier. J'ai également essayé de l'utiliser comme un entier de 16 bits comme cela a été suggéré dans l'une des autres réponses (même résultat). J'ai besoin d'utiliser des flottants pour calculer l'échantillon jusqu'au moment de l'écrire. – blkrbt

0

Aller sur un membre, mais puisque vous voulez signé des valeurs 16 bits, essayez ceci:

int16_t pcm = out * 256; 
fwrite(&pcm, sizeof(pcm), 1, fo); 

Aussi, assurez-vous que vous avez correctement marqué votre dossier, à savoir. PCM brut signé 16 bits avec l'endian-ness approprié. (edit: ce n'est pas applicable pour PCM)

+0

Cela donne un résultat identique à ce que j'ai posté ci-dessus. – blkrbt

0

Pour zombie ce fil:

De Wiki WAV:

Il y a quelques incohérences dans le format WAV: par exemple, les données 8 bits est non signée alors que les données de 16 bits est signé

+1

Veuillez fournir un lien vers l'article que vous citez. –

4

Je ne peux pas dire exactement ce qui est faux dans votre code sans le voir, mais cela vous fera une belle onde sinusoïdale 1 kHz PCM 16 bits dans Audacity qui peut être ouvert:

#include <stdio.h> 
#include <math.h> 

#ifndef M_PI 
#define M_PI 3.14159265358 
#endif 

int main(void) 
{ 
    FILE* f = fopen("sinewave.pcm", "wb"); 
    double t; 
    for (t = 0; t < 1; t += 1./8000) // 8000 is the sample rate in Hz 
    { 
    double sample = 15000 * sin(2 * M_PI * 1000 * t); // 1000 Hz sine wave 
    short s16 = (short)sample; 
    unsigned char c; 
    c = (unsigned)s16 % 256; 
    fwrite(&c, 1, 1, f); 
    c = (unsigned)s16/256 % 256; 
    fwrite(&c, 1, 1, f); 
    } 
    fclose(f); 
    return 0; 
} 

Dans Audacity naviguer dans Fichier-> Importer-> Données brutes:

Encoding: Signé PCM
16 bits Byte Order: petit-boutiste
Canaux: 1 Channel (Mono)
Taux d'échantillonnage: 8000

Importation.

Questions connexes