ComponentResult create_sample_description__flac(StreamInfo *si) { ComponentResult err = noErr; Handle desc; AudioStreamBasicDescription asbd; AudioChannelLayout acl; AudioChannelLayout *pacl = &acl; ByteCount acl_size = sizeof(acl); asbd.mSampleRate = si->rate; asbd.mFormatID = kAudioFormatXiphOggFramedFLAC; asbd.mFormatFlags = 0; asbd.mBytesPerPacket = 0; asbd.mFramesPerPacket = 0; //asbd.mBytesPerFrame = 2 * si->numChannels; asbd.mBytesPerFrame = 0; asbd.mChannelsPerFrame = si->numChannels; //asbd.mBitsPerChannel = 16; //asbd.mBitsPerChannel = 0; asbd.mBitsPerChannel = si->si_flac.bps; asbd.mReserved = 0; acl.mChannelBitmap = 0; acl.mNumberChannelDescriptions = 0; switch (si->numChannels) { case 1: acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; break; case 2: acl.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; break; case 3: acl.mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_0; break; case 4: acl.mChannelLayoutTag = kAudioChannelLayoutTag_Quadraphonic; break; case 5: acl.mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_2; break; case 6: acl.mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_2_1; break; default: pacl = NULL; acl_size = 0; } err = QTSoundDescriptionCreate(&asbd, pacl, acl_size, NULL, 0, kQTSoundDescriptionKind_Movie_Version2, (SoundDescriptionHandle*) &desc); if (err == noErr) { si->sampleDesc = (SampleDescriptionHandle) desc; } return err; };
void ofxQtAudioRecorder::prepareAudioRecording(int sampleRate, int numChannels_){ OSErr err = noErr; // create audio description and set format ID along with format flags, mBitsPerChannel and mBytesPerPacket AudioStreamBasicDescription asbd; numChannels = numChannels_; asbd.mSampleRate = sampleRate; asbd.mFormatID = kAudioFormatLinearPCM; asbd.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; // if multi-channel, the data format must be interleaved (non-interleaved is not allowed), // and you should set up the asbd accordingly asbd.mChannelsPerFrame = numChannels; // 2 (Stereo) // mBitsPerChannel = number of bits of sample data for each channel in a frame of data asbd.mBitsPerChannel = sizeof (Float32) * 8; // was 8 // 32-bit floating point PCM // mBytesPerFrame = number of bytes in a single sample frame of data // (bytes per channel) * (channels per frame) = 4 * 2 = 8 asbd.mBytesPerFrame = (asbd.mBitsPerChannel>>3) * asbd.mChannelsPerFrame; // // number of *bytes* per channel * channels per frame asbd.mFramesPerPacket = 1; // For PCM, frames per packet is always 1 // mBytesPerPacket = (bytes per frame) * (frames per packet) = 8 * 1 = 8 asbd.mBytesPerPacket = asbd.mBytesPerFrame * asbd.mFramesPerPacket; //printf("bits per channel %i\n", asbd.mBitsPerChannel); //printf("bytes per frame %i - %i %i\n", asbd.mBytesPerFrame, (asbd.mBitsPerChannel>>3), asbd.mChannelsPerFrame); //printf("bytes per packet %i\n", asbd.mBytesPerPacket); err = QTSoundDescriptionCreate(&asbd, NULL, 0, NULL, 0, kQTSoundDescriptionKind_Movie_Version2, &soundDesc); checkErr(0x0200); audioTrack = NewMovieTrack(movie, Long2Fix(0), Long2Fix(0), kFullVolume); err = GetMoviesError(); checkErr(0x0201); audioMedia = NewTrackMedia(audioTrack, SoundMediaType, sampleRate, NULL, 0); err = GetMoviesError(); checkErr(0x0202); return; }
ComponentResult create_sample_description__speex(StreamInfo *si) { ComponentResult err = noErr; Handle desc; AudioStreamBasicDescription asbd; AudioChannelLayout acl; AudioChannelLayout *pacl = &acl; ByteCount acl_size = sizeof(acl); asbd.mSampleRate = si->rate; asbd.mFormatID = kAudioFormatXiphOggFramedSpeex; asbd.mFormatFlags = 0; asbd.mBytesPerPacket = 0; asbd.mFramesPerPacket = 0; //asbd.mBytesPerFrame = 2 * si->numChannels; asbd.mBytesPerFrame = 0; asbd.mChannelsPerFrame = si->numChannels; //asbd.mBitsPerChannel = 16; asbd.mBitsPerChannel = 0; asbd.mReserved = 0; if (si->numChannels == 1) acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; else if (si->numChannels == 2) acl.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; else { pacl = NULL; acl_size = 0; } acl.mChannelBitmap = 0; acl.mNumberChannelDescriptions = 0; err = QTSoundDescriptionCreate(&asbd, pacl, acl_size, NULL, 0, kQTSoundDescriptionKind_Movie_Version2, (SoundDescriptionHandle*) &desc); if (err == noErr) { si->sampleDesc = (SampleDescriptionHandle) desc; } return err; };
static int init_audio(int speed, int channels, soundmovie_buffer_t **buffer) { AudioStreamBasicDescription asbd = {0}; //see CoreAudioTypes.h asbd.mSampleRate = speed; asbd.mFormatID = kAudioFormatLinearPCM; asbd.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger; asbd.mChannelsPerFrame = channels; asbd.mBitsPerChannel = sizeof (SWORD) * 8; asbd.mBytesPerFrame = (asbd.mBitsPerChannel >> 3) // number of *bytes* per channel * asbd.mChannelsPerFrame; // channels per frame asbd.mFramesPerPacket = 1; // For PCM, frames per packet is always 1 asbd.mBytesPerPacket = asbd.mBytesPerFrame * asbd.mFramesPerPacket; UInt32 layoutSize; layoutSize = offsetof(AudioChannelLayout, mChannelDescriptions[0]); AudioChannelLayout *layout = NULL; layout = calloc(layoutSize, 1); OSErr err = -1; if (layout != NULL) { if (channels == 1) { layout->mChannelLayoutTag = kAudioChannelLayoutTag_Mono; } else if (channels == 2) { layout->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; } else { log_debug("quicktime_audio: unsupported channels: %d", channels); return -1; } err = QTSoundDescriptionCreate( &asbd, // format description layout, layoutSize, // channel layout NULL, 0, // magic cookie (compression parameters) kQTSoundDescriptionKind_Movie_LowestPossibleVersion, &soundDescriptionHandle); // SoundDescriptionHandle returned here free(layout); } if (err != noErr) { log_debug("quicktime_audio: error creating sound description!"); return -1; } //Add audio track audioTrack = NewMovieTrack(movie, 0, 0, kFullVolume); OSStatus theError = GetMoviesError(); if (theError) { log_debug("quicktime_audio: error creating movie track"); return theError; } //Create audio track media audioMedia = NewTrackMedia(audioTrack, SoundMediaType, speed, 0, 0); theError = GetMoviesError(); if (theError) { log_debug("quicktime_audio: error creating track media!"); return theError; } //Prepare media for editing theError = BeginMediaEdits(audioMedia); if (theError) { log_debug("quicktime_audio: error beginning media edits!"); return theError; } *buffer = &audioBuffer; audioBuffer.size = speed * channels / 10; audioBuffer.buffer = malloc(sizeof(SWORD) * audioBuffer.size); audioBuffer.used = 0; audio_ready = 1; return 0; }
/* Initializes the map & targetTrack to receive audio data */ OSStatus initialize_audio_map(NCStream *map, Track targetTrack, Handle dataRef, OSType dataRefType, AVPacket *firstFrame) { Media media; SoundDescriptionHandle sndHdl = NULL; AudioStreamBasicDescription asbd; AVCodecContext *codec; UInt32 ioSize; OSStatus err = noErr; uint8_t *cookie = NULL; size_t cookieSize = 0; codec = map->str->codec; map->base = map->str->time_base; media = NewTrackMedia(targetTrack, SoundMediaType, codec->sample_rate, dataRef, dataRefType); map->media = media; memset(&asbd,0,sizeof(asbd)); map_avi_to_mov_tag(codec->codec_id, &asbd, map, codec->channels); if(asbd.mFormatID == 0) /* no known codec, use the ms tag */ asbd.mFormatID = 'ms\0\0' + codec->codec_tag; /* the number is stored in the last byte => big endian */ /* Ask the AudioToolbox about vbr of the codec */ ioSize = sizeof(UInt32); AudioFormatGetProperty(kAudioFormatProperty_FormatIsVBR, sizeof(AudioStreamBasicDescription), &asbd, &ioSize, &map->vbr); cookie = create_cookie(codec, &cookieSize, asbd.mFormatID, map->vbr); /* Set as much of the AudioStreamBasicDescription as possible. * Then ask the codec to correct it by calling FormatInfo before creating the SoundDescriptionHandle. * FormatInfo is poorly documented and doesn't set much of an example for 3rd party codecs but we can hope * they'll overwrite bad values here. */ asbd.mSampleRate = codec->sample_rate; asbd.mBytesPerPacket = codec->block_align; asbd.mFramesPerPacket = codec->frame_size; asbd.mChannelsPerFrame = codec->channels; asbd.mBitsPerChannel = codec->bits_per_coded_sample; /* ask the toolbox about more information */ ioSize = sizeof(AudioStreamBasicDescription); err = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, cookieSize, cookie, &ioSize, &asbd); // We can't recover from this (FormatInfo resets mFormatID for bad MPEG-4 AOTs) if (!asbd.mFormatID || !asbd.mChannelsPerFrame) { Codecprintf(NULL, "Audio channels or format not set\n"); goto bail; } // We might be able to recover from this (at least try to import the packets) if (err) { Codecprintf(NULL, "AudioFormatGetProperty failed (error %ld / format %lx)\n", err, asbd.mFormatID); err = noErr; } // This needs to be set for playback to work, but 10.4 (+ AppleTV) didn't set it in FormatInfo. // FIXME anything non-zero (like 1) might work here if (!asbd.mFramesPerPacket && asbd.mFormatID == kAudioFormatMPEGLayer3) asbd.mFramesPerPacket = asbd.mSampleRate > 24000 ? 1152 : 576; // if we don't have mBytesPerPacket, we can't import as CBR. Probably should be VBR, and the codec // either lied about kAudioFormatProperty_FormatIsVBR or isn't present if (asbd.mBytesPerPacket == 0) map->vbr = 1; /* If we have vbr audio, the media scale most likely has to be set to the time_base denumerator */ if(map->vbr) { /* if we have mFramesPerPacket, set mBytesPerPacket to 0 as this can cause * errors if set incorrectly. But in vbr, we just need the mFramesPerPacket * value */ if(asbd.mFramesPerPacket) asbd.mBytesPerPacket = 0; SetMediaTimeScale(media, map->str->time_base.den); } if (asbd.mFormatID == kAudioFormatLinearPCM) asbd.mFramesPerPacket = 1; else if (asbd.mBytesPerPacket) { /* FIXME: in the MSADPCM codec, we get a wrong mFramesPerPacket entry because * of the difference in the sample_rate and the time_base denumerator. So we * recalculate here the mFramesPerPacket entry */ /* For calculation, lets assume a packet duration of 1, use ioSize as tmp storage */ ioSize = map->str->time_base.num * codec->sample_rate / map->str->time_base.den; /* downscale to correct bytes_per_packet */ asbd.mFramesPerPacket = ioSize * asbd.mBytesPerPacket / codec->block_align; } AudioChannelLayout acl; int aclSize = 0; //Set this if you intend to use it memset(&acl, 0, sizeof(AudioChannelLayout)); /* We have to parse the format */ int useDefault = 1; if(asbd.mFormatID == kAudioFormatAC3 || asbd.mFormatID == 'ms \0') { QTMetaDataRef trackMetaData; OSStatus error = QTCopyTrackMetaData(targetTrack, &trackMetaData); if(error == noErr) { const char *prop = "Surround"; OSType key = 'name'; QTMetaDataAddItem(trackMetaData, kQTMetaDataStorageFormatUserData, kQTMetaDataKeyFormatUserData, (UInt8 *)&key, sizeof(key), (UInt8 *)prop, strlen(prop), kQTMetaDataTypeUTF8, NULL); QTMetaDataRelease(trackMetaData); } if(parse_ac3_bitstream(&asbd, &acl, firstFrame->data, firstFrame->size)) { useDefault = 0; aclSize = sizeof(AudioChannelLayout); } } if(useDefault && asbd.mChannelsPerFrame > 2) { acl = GetDefaultChannelLayout(&asbd); aclSize = sizeof(AudioChannelLayout); } if (asbd.mSampleRate > 0) { err = QTSoundDescriptionCreate(&asbd, aclSize == 0 ? NULL : &acl, aclSize, cookie, cookieSize, kQTSoundDescriptionKind_Movie_LowestPossibleVersion, &sndHdl); if(err) { fprintf(stderr, "AVI IMPORTER: Error %ld creating the sound description\n", err); goto bail; } } map->sampleHdl = (SampleDescriptionHandle)sndHdl; map->asbd = asbd; bail: if(cookie) av_free(cookie); return err; } /* initialize_audio_map() */